JavaScript 中的 this 关键字

与其他语言相比,函数的 this 关键字在 JavaScript 中的表现略有不同,此外,在严格模式和非严格模式之间也会有一些差别。

在绝大多数情况下,函数的调用方式决定了this的值。this不能在执行期间被赋值,并且在每次函数被调用时this的值也可能会不同。ES5引入了bind方法来设置函数的this值,而不用考虑函数如何被调用的,ES2015 引入了支持this词法解析的箭头函数(它在闭合的执行上下文内设置this的值)。

作为 JavaScript 中一个最扑朔迷离的关键字,this 也成为面试中最受考官欢迎并使用的一个考点。看了一些文章后,你可能越看越迷糊,这很正常。不过今天我以 MDN 的文档库为基础,把一些学习心得记录一下。

定义

this 是函数作用域中自动生成的特殊的标识符关键字,可以将它当作一个指针来理解。

不同环境下的 this 指向

按照 ECMAScript 规范我们讨论两种常用可执行代码(上下文环境):

  • 全局代码(Global code)
  • 函数代码(Function code)

1、全局上下文

无论是否在严格模式下,在全局执行上下文中(在任何函数体外部)this 都指代全局对象。

// 在浏览器中, window 对象同时也是全局对象:
console.log(this === window); // true

a = 37;
console.log(window.a); // 37

this.b = "MDN";
console.log(window.b)  // "MDN"
console.log(b)         // "MDN"

2、函数上下文

在函数内部,this 的值取决于函数被调用的方式。以下我们简单讨论三种。

2.1 简单调用

因为下面的代码不是在严格模式下执行,且 this 的值不是通过调用设置的,所以 this 的值默认指向全局对象。

function f1(){
  return this;
}
// 在浏览器中:
f1() === window;   // 在浏览器中,全局对象是window

// 在Node中:
f1() === global;

然而,在严格模式下,this 将保持他进入执行上下文时的值,所以下面的this将会默认为 undefined

function f2(){
  "use strict"; // 这里是严格模式
  return this;
}

f2() === undefined; // true

所以,在严格模式下,如果 this 未在执行的上下文中定义,那它将会默认为 undefined

2.2 作为对象的方法

当以对象里的方法的方式调用函数时,它们的 this 是调用该函数的对象。

var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};

console.log(o.f()); // logs 37

我们也可以首先定义函数,然后再将其附属到 o.f。这样做会导致相同的行为,也就是说,这样的行为不受函数定义方式或位置的影响。

var o = { prop: 37 };

function independent() {
  return this.prop;
}

o.f = independent;

console.log(o.f()); // logs 37

类似的,this 的绑定只受最靠近的成员引用的影响。

o.b = { g: independent, prop: 42 };
console.log(o.b.g()); // 42

2.3 作为构造函数

当一个函数用作构造函数时(使用 new 关键字),它的 this 被绑定到正在构造的新对象。

简单总结

最后,引用知乎的几个简单论断:

  • this 永远指向函数运行时所在(最近)的对象,而不是函数被创建时所在的对象;
  • 如果是 callapplywith,指定的 this 是谁,就是谁;
  • 普通的函数调用,函数被谁调用,this 就是谁。

参考

1、根治JavaScript中的this-ECMAScript规范解读
2、你不懂JS: this 与对象原型 - this 是什么?
3、你不懂JS: this 与对象原型 - 第二章: this 豁然开朗!
4、JS 中 this 关键字详解
5、彻底理解js中this的指向,不必硬背
6、用自然语言的角度理解JavaScript中的this关键字

你可能感兴趣的:(JavaScript 中的 this 关键字)