在 JavaScript中,this 是在**
运行时而不是编写时绑定**的。
- 隐式绑定:
当我们把对象里的方法赋值给一个全局变量时,这种绑定就消失了
function logger() {
console.log( this.a );
}
var obj = {
a: 3,
logger: logger
};
var a = 2;
var objLogger = obj.logger;
objLogger(); // 2
- 显示绑定:call 或者 apply
- 硬性绑定:bind
无论后续我们怎么调用 hardBinding 函数,logger 都会把 obj 当做 this 来获取它的 a 属性的值。
function logger() {
console.log( this.a );
}
var obj = {
a: 3
};
var hardBinding = logger.bind( obj );
setTimeout( hardBinding, 1000 ); // 3
hardBinding.call( window ); // 3
- new 绑定
function logger(a) {
this.a = a;
}
var obj1 = {};
var hardBinding = logger.bind( obj1 );
hardBinding( 2 );
console.log( obj1.a ); // 2
var obj2 = new logger( 3 );
console.log( obj1.a ); // 2
console.log( obj2.a ); // 3
- 箭头函数
我们使用箭头函数的时候,this 是在词法域里面的,而不是根据函数执行时的上下文。
箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承 this
function logger() {
return (a) => {
console.log( this.a );
};
}
var obj1 = {
a: 2
};
var obj2 = {
a: 3
};
var logger1 = logger.call( obj1 );
logger1.call( obj2 ); // 2
setTimeout 场景使用
function logger() {
setTimeout(() => {
console.log( this); // {a: 2}
},1000);
}
var obj = {
a: 2
};
function logger() {
setTimeout(function() {
console.log( this); // Window
},1000);
}
var obj = {
a: 2
};
function logger() {
var self = this;
setTimeout( function(){
console.log( self.a ); // 2
}, 1000 );
}
var obj = {
a: 2
};
logger.call( obj );
常见错误
JavaScript 新手经常犯的一个错误是**将一个方法从对象中拿出来,然后再调用**
期望方法中的 this 是原来的对象(比如在回调中传入这个方法)。
如果不做特殊处理的话,一般会丢失原来的对象。
基于这个函数,用原始的对象创建一个绑定函数,巧妙地解决了这个问题:
this.x = 9; // 在浏览器中,this 指向全局的 "window" 对象
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81
var retrieveX = module.getX;
retrieveX();
// 返回 9 - 因为函数是在全局作用域中调用的
// 创建一个新函数,把 'this' 绑定到 module 对象
// 新手可能会将全局变量 x 与 module 的属性 x 混淆
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81