new & this & prototype
Clear
new 关键字深入, this绑定规则, 继承1.new
new的作用
一般面向类编程语言new是调用类的构造方法、创建类的实例
所以在JavaScript中new的作用是一样吗? JavaScript中new的机制实际上和面向类的语言完全不同
首先我们重新定义一下JavaScript中的 "构造函数"。在JavaScript中、构造函数只是一些使用new操作符时,被调用的函数
它们并不会属于某个类,也不会实例化一个类,它们只是被new操作符调用的普通函数而已
使用new来调用函数,或者说发生构造函数调用时,会自动执行下面的操作
- 创建(或者说构造)一个全新的对象
- 这个新对象会被执行[[原型]]连接
- 这个新对象会绑定到函数调用的this
- 如果函数没有返回其他对象, 那么new表达式中的函数调用会自动返回这个新对象
以上摘抄自《你不知道的JavaScript》, 所以总结来说
new就是创建对象,连接原型,并绑定thisnew执行它则被称为一个自定义的类,会默认创建一个对象,而这个对象就是当前类的实例
其this指向这个新创建的实例
模拟new的实现
不建议通过__proto__修改对象的属性[[Protoytpe]]属性
测试demo
参考链接
2.this
this的绑定机制
this是在运行时进行绑定的,并不是在编写时, 它指向什么完全取决于函数在哪里被调用
当一个函数被调用时,会创建一个活动记录(执行上下文), 这个记录会包含函数在哪里被调用(调用栈), 函数的调用方法,传入的参数等信息。this就是记录的其中一个属性
this的绑定规则
1.默认绑定
非严格模式(non-strict mode) this指向全局对象
严格模式(strict mode)全局对象将无法使用默认绑定, this会绑定到undefined
2.隐式绑定
当函数中有上下文对象时, 隐式规则会把函数调用中的this绑定到这个上下文对象
函数传递其实就是一种隐式绑定,因此我们传入函数时也会被隐式赋值
就像我们看到的那样, 回调函数丢失this绑定是非常常见的
在分析隐式绑定时,我们必须在一个对象的内部,包含一个指向函数的属性
并通过这个属性,间接引用函数, 从而把this(隐式)绑定到这个对象
3.显示绑定
可以使用函数的 call(..) 和 apply(..) 方法
4.new绑定
优先级
函数是在new中调用(new 绑定),this绑定的是新创建的对象 var bar = new foo()
函数通过call, apply(显示绑定)或者硬绑定, this绑定的是指定的对象 var bar = foo.call(obj)
函数在某个上下文对象中调用(隐式绑定), this绑定的是那个上下文对象 var bar = obj.foo()
如果上门三种都不是, 使用默认绑定, 如果在严格模式下,就绑定到undefined,否则绑定到 全局对象。 var bar = foo()
如果把null或者undefined作为this的绑定对象传入call, apply, bind, 这些值在调用时会被忽略
this词法、箭头函数
ES6中的arrow function不适用于以上规则, 而是根据外层作用域来决定this
最后在来总结一下😳
由new调用? 绑定到新创建的对象
由call或者apply(bind)调用? 绑定到指定的对象
由上下文调用? 绑定到该上下文
默认: 严格模式下绑定到undefined, 否则绑定到全局对象
Prototype
JavaScript 会在两个对象之间创建一个关联,这样其中一个对象就可以通过委托访问另一个对象的属性和函数
NotingSpecial只是一个普通的函数,但是当使用new调用时,它就会构造一个对象并赋值给a
这看起来像是new的一个副作用,但是NotingSpecial本身并不是一个构造函数
换句话说, 在JavaScript中对于"构造函数"最准确的解释是,所有带new的函数调用
函数不是构造函数,但是当使用new时, 函数调用会变成"构造函数调用"

ES6 语法
ES6中, 我们可以在任意对象的字面形式中使用简洁方法声明(concise method declatation)
字面形式与class区别:字面形式使用, 来分割元素
class陷阱: class 并不会像传统面向类的语言一样在声明时静态复制所有的行为. 如果你修改或者替换父类的一个方法,那么子类和所有实例都会受到影响 因为它们在定义时并没有进行复制,只是基于prototype的委托
Object
| 语法元素 | 含义 |
|---|---|
| for ... in | 列举对象成员名 |
| for ... of | 列举数组成员值 |