js 中 this 指向(绑定)
函数在运行时会自动生成一个内部对象(执行上下文),而 this 指向的就是这个对象(执行上下文),所以 this 的指向也是动态的。
this 指向(绑定)与函数调用的位置有关。
箭头函数是没有 this 的,其永远指向全局(window/undefined)。其实质是代码在编译的时候就已经定义好了。
默认绑定
在非严格模式下,全局环境中 this 绑定是 window 对象,这也被称为默认绑定。
- 直接在全局调用 this;
- 在全局直接执行函数,函数中直接调用 this;
注意: esm 默认开始严格模式,去掉
type="module就可以了。
注意在对象中某个属性的值是一个引用函数时,应该使用回调函数或者匿名函数将这个引用的函数包裹起来,避免在执行上下文的时候直接调用,而不是通过这个对象的属性访问之后才调用的。
全局(window)添加属性
- 在全局作用域下使用 var 声明变量;
- 直接使用
window.x; - 在默认绑定的情况下直接使用 this(非严格模式);
隐式绑定
作为某个对象的方法(上下文对象)调用,this 绑定的是这个对象(上下文对象),这写也被称为隐式绑定。
注意:
- 如果该函数(方法)是箭头函数,无论有几层嵌套对象,this 会进行默认绑定(window/undefined)。
匿名函数和具名函数则不受其影响。
- 如果将该对象的函数赋值给了另一个变量,在全局中直接调用该变量对应的函数,也是相当于默认绑定。这也被称为绑定丢失现象。
const obj = {
a: 10,
b: function () {
console.log(this);
},
};
const copy_obj = obj.b;
copy_obj(); // undefined / window
obj.b(); // {a: 10, b: ƒ}
new 绑定
通过 new 关键字调用的函数会生成一个实例对象,this 绑定的就是这个实例对象。
注意:如果在这个构造函数中返回了一个引用数据类型(对象、数组、函数),this 指向的就是这个引用数据类型。
实例对象可以使用构造函数中this绑定的值,因为this绑定的就是整个实例对象。如果在实例对象(this)上找不到所访问的属性,就会去它的原型对象上找,遍历整条原型链条直到找到这个值或者 null 为止(null 返回 undefined)。
对象原型
js 中每一个函数都有一个原型对象(prototype),通过 new 关键字(构造函数)生成的实例对象都可以访问这个原型对象上的属性和方法。
实例对象可以通过__proto__属性访问这个原型对象;
原型对象可通通过constructor属性访问这个实例对象的构造函数;
原型对象也有它的原型对象,直到获取到 Object 的原型的原型(null)为止,就这样组成了一条原型链。
模式
使用 this 和原型对象可以实现类似继承的效果。
todo… which parttern
显示绑定
使用call()、apply()、bind()时,this 绑定的是指定对象。
- call():一个一个传参;
- apply():传递一个数组;
- bind():直接返回一个新函数;
其他
- 可以使用
Object.create(null)创建一个没有 this 绑定的对象; - 箭头函数会继承外层函数调用的 this 绑定(window/undefined);
- es6 之前的 self 同 this 机制;