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的指向。
 
             
           
             
          
评论区