js 中的 this
this 的值
非严格模式下,this 总是指向一个对象
严格模式下,this 可以是任意值
无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象
this 到底指向谁
和 this 相关的函数的常用调用方式:
纯粹的函数调用
作为对象方法的调用
call 调用 或 apply 调用
作为构造函数调用
来看一道题:
var x = 0;
var y = 1;
// 普通函数
function test() {
console.log(this.x);
}
// 构造函数
function Test2() {
this.y = 2;
}
var obj = {
x: 1,
test: test,
};
var obj2 = new Test2();
var arr = [test, new Test2()];
// ----- 以下各调用方式中的this值就是call()中的第一个参数 -----
// 纯粹的函数调用
test(); // 打印 0 该式可看作:test.call(undefined)
// 作为对象方法的调用
obj.test(); // 打印 1 该式可看作:obj.test.call(obj)
// call 调用 或 apply 调用
obj.test.call(); // 打印 0 该式可看作:obj.test.call(undefined)
obj.test.call(obj); // 打印 1
// 作为构造函数调用
console.log(obj2.y); // 打印 2 该式可看作:obj2.y.call(obj2)
// 在数组中
arr[0](); // 打印 undefined 该式可看作 arr.0.call(arr)
arr[1].y; // 值为 2 该式可看作 arr[1].y.call(arr[1])以上我们最常见到的是类似 test(arg1,arg2, ...) obj.test(arg1,arg2, ...) 这样 的调用方式,而很少使用类似 obj.test.call(thisArg,arg1,arg2, ...) 这样的调用方 式。所以才会搞不清楚 this 到底指向了哪里。
test(arg1,arg2, ...) 等价于 test.call(undefined,arg1,arg2, ...)
obj.test(arg1,arg2, ...) 等价于obj.test.call(obj,arg1,arg2, ...)
所以总结起来都是在以 func.call(thisArg,arg1,arg2, ...) 这样的的方式调用函数。
那么 this 所指向的值就很明了了:
** this 的值,就是 call(thisArg,arg1,arg2, ...) 里的 thisArg 的值。**
call 函数和 apply 函数用法类似,所以这里就不讨论 apply 了。
需要注意的是:call 函数中指定的 this 值并不一定是该函数执行时真正的 this 值,如 果这个函数处于 non-strict mode 模式,则指定为 null 和 undefined 的 this 值会自动 指向全局对象(浏览器中就是 window 对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象(严格模式下默认 thisArg 是 undefined)。
ES6 中箭头函数与 this
先看个示例(不建议在定义对象的方法时使用箭头函数,这里只是为了探讨问题而使用):
tool 方法用箭头函数定义,tool2 方法用普通函数定义。
从 obj.tool.call(obj) // 打印 window 对象 可以看出,即使用 call 指定了 this 值 为 obj,打印出来的依然是 window 对象。而 obj.tool2.call(obj) // 打印 obj 对象 就正常输出 call 指定的 obj 对象。
阮一峰老师的 ES6 教程里是这样解释的: 箭头函数内的 this 对象,就是定义时所在的 对象,而不是使用时所在的对象。
回到这个例子中,就是说 箭头函数 tool 定义时所在的作用域为全局作用域,所以它里面 的 this 指向 window 。这里会有很多人不能理解,tool 不是 obj 中定义的方法吗?怎么 会指向 window 。我最开始也一脸迷茫,想了好久才明白:
this 值的判断条件并 不是对象,而是 所在作用域 ,js 只有 函数作用域 和 全局作用域 (这里先说 ES5,ES6 暂不讨论)所以可以这样理解: 箭头函数中 必须通过查找作用域来确定其 this 值,简单来说就是:箭头函数中 this 绑定的是距它最 近一层非箭头函数作用域的 this 值。
箭头函数 tool 往外一层就是全局作用域了,所以 tool 中的 this 就是 window 。
这样理解还是有点复杂,再简化一下:箭头函数里没有 this ,如果里面出现 this ,就 向上查找最近的 this 值来使用。
再来看一个例子:
再看一个例子:
类中的 this
和其他普通函数一样,类的实例的方法中的 this 值取决于它们如何被调用,有时,改写这 个行为,让类中的 this 值总是指向这个类实例会很有用。为了做到这一点,可在构造函数 中绑定类方法。
仔细看下题:
Last updated
Was this helpful?