feng xiaohan

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 机制;