javascript 中的 this 判定

this 关键字是 JavaScript 中比较复杂的机制之一,它是一个很特别的关键字,被自动定义在所有函数的作用域中。人们很容易把 this 理解成指向函数自身,这其实是不对的。每个函数的 this 是在调用时被绑定的,取决于函数的调用位置。

绑定规则

默认绑定

这是最常用的函数调用类型即独立函数调用,当无法应用其他规则时,便走这条默认规则。此时 this 会被绑定到全局对象,严格模式下会被绑定到 undefined 。

首先我们来看下面这段代码

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

var a = 2;

test(); // 2

我们可以看到当 test 函数被调用时,this.a 指向了我们定义的全局变量 a。这里 test 函数是独立函数的调用,应用的是默认绑定的规则,此时 this 指向全局对象。

我们再来看看使用严格模式时的运行情况

function test() {
  'use strict';
  console.log(this.a);
}

var a = 2;

test(); // TypeError: Cannot read property 'a' of undefined

可以看到,在严格模式下,this 将会绑定到 undefined。

隐式绑定

这条规则是要考虑调用位置是否有上下文对象。此时 this 被绑定到这个上下文对象上面。

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

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

obj.test(); // 2

可以看到 test 函数是使用 obj 这个上下文对象来调用的,此时 this 会绑定到 obj 这个上下文对象,this.a 其实就是 obj.a 都是 2。

显式绑定

显式绑定是指我们通过 call 、apply 方法强制改变函数运行时的上下文对象。它们的第一个参数是一个对象,函数调用时 this 就会绑定到这个对象上面。

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

var obj = {
  a: 2
};

test.call(obj); // 2

我们通过 test.call(obj) 强制把 this 绑定到 obj 上。这里我们想一下,如果把 null、undefined 作为 this 的绑定对象传入会怎么样呢?

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

var obj = {
  a: 2
};

var a = 1;

test.call(null); // 1

test.call(undefined); // 1

可以看到,当显示绑定到 null、undefined 时,这些值在函数调用时会被忽略,此时会使用默认规则来绑定 this 到全局对象。

new 绑定

我们首先先要了解下通过 new 来调用函数,发生了哪些步骤。

1. 创建一个全新的对象

2. 新对象会被执行原型连接

3. 新对象会绑定到函数调用的 this

4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象

我们看下面代码

function Test (a) {
  this.a = a;
}

var test = new Test(2);

test.a // 2

使用 new 来调用函数 Test 时,会创建一个新的对象并且把它绑定到 Test 调用中的 this 上。

优先级

我们已经知道了 this 指向的 4 条规则,那么当一个函数调用时同时满足多条规则时该怎么办呢?这时候我们确定这 4 条规则的优先级。

记住: new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定。

所以我们可以按照下列顺序来判断 this 指向:

  1. new 绑定:函数是否是通过 new 调用的?如果是那么 this 绑定的就是新创建的对象。

  2. 显式绑定:函数是否通过 call、apply 调用的?如果是那么 this 绑定的就是指定的对象。

  3. 隐式绑定:函数是否在某个上下文对象中调用?如果是那么 this 绑定的就是那个上下文对象。

  4. 默认绑定:如果以上都不是的话,使用默认绑定。this 绑定到全局对象上,注意如果在严格模式下,this 会绑定到 undefined 上。

值得一提的是,ES6 中的箭头函数并不会使用以上四条绑定规则,箭头函数会继承外层函数调用的 this 绑定。其实和 ES6之前代码中的 var self = this 机制一样。

更多精彩内容,欢迎关注微信公众号~

原文地址:https://www.cnblogs.com/alsy/p/12245713.html