现在有一个构造函数,里面注册了一个事件处理器:
function Constructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
var obj = new Constructor('foo', transport);
但是在回调函数中无法访问对象的data属性,看起来不是指向创建的对象,而是另一个对象。
如果不使用匿名函数,使用对象方法如下:
function Constructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
Constructor.prototype.alert = function() {
alert(this.name);
};
但是也出现了相同的问题,如何才能访问到正确的对象?
关于this
This是每个函数中的一个特殊的关键字,它的值只取决于函数是如何调用的,而不是如何/何时/何地定义的。它不像其他变量一样受词法范围的影响(箭头函数除外,见下文)。下面是一些例子:
function foo() {
console.log(this);
}
// 普通函数调用
foo(); // this指的是`window`对象
//作为对象函数
var obj = {bar: foo};
obj.bar(); // 这里的this指的是对象`
//作为构造函数
new foo(); // this为该对象
如何正确地使用this?
不要使用this
实际上你并不需要访问this,而是它引用的对象。这就是为什么一个简单的解决方案是创建一个新的变量,它也引用那个对象。变量可以有任何名称,但常见的名称是self等等:
function Constructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function() {
alert(self.data);
});
}
由于self是一个普通变量,所以它遵守词法作用域规则,并且可以在回调函数中访问。这还有一个好处,你可以访问回调本身的这个值。
显示地设置回调函数的this
你可能无法控制this值,因为它的值是自动设置的,但实际情况并非如此。每个函数都有.bind方法,该方法返回一个新函数,并将其绑定到一个值。该函数具有与你调用.bind的函数完全相同的行为,只是这是你设置的。无论如何或何时调用该函数,它总是引用传递的值。
function Constructor(data, transport) {
this.data = data;
var boundFunction = (function() {
alert(this.data);
}).bind(this);
transport.on('data', boundFunction);
}
在本例中,我们将回调函数的this绑定到Constructor的this的值。注意:当为jQuery绑定上下文时,使用jQuery.proxy这样做的原因是,在解绑定事件回调时,不需要存储对函数的引用。jQuery在内部处理这个问题。
ECMAScript6: 使用箭头函数
一些接受回调的函数/方法也接受这个回调应该引用的值。这基本上与你自己绑定它是一样的,但是函数/方法为你完成了这一点。Array#map就是这样一个方法。它的特征是:array.map(callback [, thisArg])。
第一个参数是回调函数,第二个参数是this该引用的值,下面是一个常见的例子:
var arr = [1, 2, 3];
var obj = {multiplier: 42};
var new_arr = arr.map(function(v) {
return v * this.multiplier;
}, obj);
评论前必须登录!
注册