this
的指向规则
this
的指向取决于函数的调用方式,总结如下:
- 有所属对象时:指向所属对象
- 无所属对象时:严格模式下指向
undefined
,非严格模式下指向全局对象(浏览器中是window
,Node.js 中是global
) new
实例化后:指向新对象- 通过
apply
、call
或bind
:指向绑定的对象
1. 函数有所属对象时:指向所属对象
var myObject = { value: 100 };
myObject.getValue = function () {
console.log(this.value); // 输出 100
console.log(this); // 输出 { value: 100, getValue: [Function] }
return this.value;
};
console.log(myObject.getValue()); // => 100
分析
getValue
函数属于 myObject
对象,并由 myObject
调用,因此 this
指向 myObject
。
2. 函数没有所属对象:严格模式与非严格模式行为不同
"use strict";
var foo = function () {
console.log(this); // 严格模式下输出 undefined
};
foo();
var fooNonStrict = function () {
console.log(this); // 非严格模式下输出全局对象 window
};
fooNonStrict();
分析
- 在严格模式下,独立调用函数时,
this
指向undefined
。 - 在非严格模式下,
this
指向全局对象。
var myObject = { value: 100 };
myObject.getValue = function () {
var foo = function () {
console.log(this.value); // 严格模式下报错,非严格模式下为 undefined
console.log(this); // 严格模式下为 undefined,非严格模式下为全局对象
};
foo();
return this.value;
};
console.log(myObject.getValue()); // => 100
补充
可以通过使用箭头函数将内部函数的 this
固定为外部函数的 this
:
myObject.getValue = function () {
var foo = () => {
console.log(this.value); // 输出 100
};
foo();
return this.value;
};
console.log(myObject.getValue()); // => 100
箭头函数不绑定自己的 this
,而是继承自外部作用域。
3. new
实例化后:指向新对象
var SomeClass = function() {
this.value = 100;
};
var myCreate = new SomeClass();
console.log(myCreate.value); // 输出 100
补充
如果构造函数显式返回一个对象,this
会指向返回的对象;否则仍指向实例化对象。
function SomeClass() {
this.value = 100;
return { anotherValue: 200 };
}
var instance = new SomeClass();
console.log(instance.value); // undefined
console.log(instance.anotherValue); // 200
4. 通过 apply
、call
或 bind
:指向绑定的对象
var myObject = { value: 100 };
var foo = function() {
console.log(this);
};
foo(); // 非严格模式下输出全局对象 window,严格模式下输出 undefined
foo.apply(myObject); // 输出 { value: 100 }
foo.call(myObject); // 输出 { value: 100 }
foo.apply(); // 参数为空时,非严格模式下指向全局对象,严格模式下为 undefined
foo.call(); // 同上
var newFoo = foo.bind(myObject);
newFoo(); // 输出 { value: 100 }
补充
apply
和 call
允许传入多个参数:
var sum = function (a, b) {
console.log(this);
return a + b;
};
console.log(sum.apply(myObject, [10, 20])); // => 30
console.log(sum.call(myObject, 10, 20)); // => 30
补充:方法调用中的 this
丢失问题
当对象方法赋值给其他变量或作为回调函数时,this
的指向可能会丢失:
var myObject = {
value: 100,
getValue: function () {
console.log(this.value);
}
};
var fn = myObject.getValue;
fn(); // 非严格模式下输出 undefined(严格模式下报错)
可以使用 bind
修复:
var boundFn = myObject.getValue.bind(myObject);
boundFn(); // 输出 100
总结
this
的指向依赖调用方式,非定义方式。- 严格模式与非严格模式会导致
this
行为不同。 - 使用箭头函数、
bind
、apply
或call
可以显式修改this
的指向。
评论区