Toc
  1. 调用位置
  2. 绑定规则
    1. 默认绑定
    2. 隐式绑定
      1. 隐式丢失
    3. 显式绑定
    4. new 绑定
  3. 优先级
  4. this判断
Toc
0 results found
FBB
你不知道的JavaScript 之 this
2020/01/16 前端 JS

最近把《你不知道的 JavaScript》重读了一遍,其中关于 this 的指向问题,将在这篇文章中做一个小小的总结。

调用位置

每个函数的 this 是在调用时被绑定的,完全取决于函数的调用位置

绑定规则

默认绑定

常用的函数调用类型:独立函数调用,this 指向全局对象。这条规则可以看作是无法应用其他规则时的默认规则。

function foo() {
  console.log(this.a);
}
var a = 2;
foo(); //2

//如果在严格模式(strict mode),那么全局对象将无法使用默认绑定,由此this会绑定到undefined上。
function foo() {
  "use strict";
  console.log(this.a);
}
var a = 2;
foo(); // TypeError: this is undefied
隐式绑定

绑定规则:调用位置是否具有上下文对象。

当引用拥有上下文对象时,隐式绑定规则会把函数调用中的 this 绑定到这个上下文对象中。

function foo() {
  console.log(this.a);
}

var obj = { a: 2, foo: foo };
obj.foo(); //2,使用obj上下文来引用函数。

对象属性引用链中只有最顶层或者为最后一层会影响调用位置。

function foo() {
  console.log(this.a);
}

var obj = { a: 2, foo: foo };
var obj1 = { a: 12, obj: obj };
obj1.obj.foo();
隐式丢失

常见的 this 绑定问题就是隐式绑定的函数会丢失绑定对象,会应用默认绑定,把 this 绑定到全局对象或者 undefined 上,这也取决于是否为严格模式。

function foo() {
  console.log(this.a);
}

var obj = {
  a: 2,
  foo: foo
};

var bar = obj.foo;
var a = "oops, global";
bar();
// bar是obj.foo函数的引用,实际上引用的是foo函数本身
// 所以此时bar函数是不带任何修饰的函数调用,因此为默认绑定

当函数作为回调函数传入。

function foo() {
  console.log(this.a);
}

function doFoo(fn) {
  // fn其实引用的就是foo
  fn(); //foo的调用位置
}

var obj = {
  a: 2,
  foo: foo
};

var a = "oops, global";
doFoo(obj.foo);
显式绑定

当不想在对象内部包含一个函数的属性时,可以使用 apply()或者 call()函数。它们的第一个参数都是对象,它们会把这个函数绑定到第一个对象参数上,在函数调用时 this 指向这个对象。
apply/call 只是参数调用方式不一样(两者的原生实现)。

new 绑定

使用 new 来调用函数,或者说发生构造函数调用时,会自动执行下面的操作(代码实现)

  1. 创建(或者说构造)一个全新的对象。
  2. 这个新对象会被执行原型连接。
  3. 这个新对象会绑定到函数调用的 this。
  4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。

优先级

new绑定 > 显示绑定 > 隐式绑定 > 默认绑定

this判断

  • 函数是否在new中调用(new绑定)。如果是,this指向新创建对象。
  • 函数是否通过apply/call绑定。如果是,this绑定的是指向对象。
  • 函数是否存在于某个上下文调用中。如果是,this绑定的是当前上下文。
  • 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到
    全局对象。
打赏
支付宝
微信
本文作者:FBB
版权声明:本文首发于FBB的博客,转载请注明出处!