与其他语言相比,函数的
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
永远指向函数运行时所在(最近)的对象,而不是函数被创建时所在的对象; - 如果是
call
、apply
、with
,指定的this
是谁,就是谁; - 普通的函数调用,函数被谁调用,
this
就是谁。
参考
1、根治JavaScript中的this-ECMAScript规范解读
2、你不懂JS: this 与对象原型 - this 是什么?
3、你不懂JS: this 与对象原型 - 第二章: this 豁然开朗!
4、JS 中 this 关键字详解
5、彻底理解js中this的指向,不必硬背
6、用自然语言的角度理解JavaScript中的this关键字
网友评论