P粉9211300672023-08-21 14:13:52
bind()
函数。bind()
函数function MyConstructor(data, transport) {
this.data = data;
transport.on('data', ( function () {
alert(this.data);
}).bind(this) );
}
// 模拟传输对象
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// 调用方式
var obj = new MyConstructor('foo', transport);
如果您使用Underscore.js - http://underscorejs.org/#bind
transport.on('data', _.bind(function () { alert(this.data); }, this));
function MyConstructor(data, transport) {
var self = this;
this.data = data;
transport.on('data', function() {
alert(self.data);
});
}
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
P粉1761515892023-08-21 10:04:21
this
的知识this
(也称为“上下文”)是每个函数内部的特殊关键字,其值仅取决于函数的调用方式,而不是定义方式。它不受词法作用域的影响,与其他变量不同(除了箭头函数,见下文)。以下是一些示例:
function foo() { console.log(this); } // 普通函数调用 foo(); // `this` 将引用 `window` // 作为对象方法 var obj = {bar: foo}; obj.bar(); // `this` 将引用 `obj` // 作为构造函数 new foo(); // `this` 将引用从 `foo.prototype` 继承的对象
要了解更多关于 this
的知识,请参阅MDN文档。
this
ECMAScript 6 引入了箭头函数,可以将其视为lambda函数。它们没有自己的this
绑定。相反,this
在作用域中查找,就像普通变量一样。这意味着你不需要调用.bind
。它们还具有其他特殊行为,请参阅MDN文档了解更多信息。
function MyConstructor(data, transport) { this.data = data; transport.on('data', () => alert(this.data)); }
this
实际上,你不需要特别访问this
,而是需要访问它所指的对象。因此,一个简单的解决方案是创建一个新变量,也指向该对象。变量可以有任何名称,但常见的是self
和that
。
function MyConstructor(data, transport) { this.data = data; var self = this; transport.on('data', function() { alert(self.data); }); }
由于self
是一个普通变量,它遵循词法作用域规则,并且可以在回调函数内部访问。这还有一个优点,即可以访问回调函数本身的this
值。
this
- 第一部分看起来你无法控制this
的值,因为它的值是自动设置的,但实际上并非如此。
每个函数都有一个方法.bind
[文档],它返回一个将this
绑定到一个值的新函数。该函数的行为与你调用.bind
时的函数完全相同,只是this
由你设置。无论如何或何时调用该函数,this
将始终引用传递的值。
function MyConstructor(data, transport) { this.data = data; var boundFunction = (function() { // 括号不是必需的 alert(this.data); // 但可能提高可读性 }).bind(this); // <- 这里我们调用了`.bind()` transport.on('data', boundFunction); }
在这种情况下,我们将回调函数的this
绑定到MyConstructor
的this
值。
注意:对于jQuery的绑定上下文,使用jQuery.proxy
[文档]。这样做的原因是在解绑事件回调时不需要存储对函数的引用。jQuery在内部处理这个。
this
- 第二部分一些接受回调函数的函数/方法也接受一个值,该值应该作为回调函数的this
。这与手动绑定相同,但是函数/方法会为你执行绑定。例如,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); // <- 这里我们将`obj`作为第二个参数传递
注意:是否可以传递this
的值通常在函数/方法的文档中提到。例如,jQuery的$.ajax
方法 [文档]描述了一个名为context
的选项:
这个问题的另一个常见表现形式是将对象方法用作回调/事件处理程序。在JavaScript中,函数是一等公民,术语“方法”只是指一个作为对象属性值的函数。但是该函数与其“包含”对象之间没有特定的链接。
考虑以下示例:
function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = function() { console.log(this.data); };
函数this.method
被分配为点击事件处理程序,但是如果点击document.body
,记录的值将是undefined
,因为在事件处理程序内部,this
指的是document.body
,而不是Foo
的实例。
如前所述,this
引用的是函数如何调用,而不是如何定义。
如果代码如下所示,可能更明显函数没有隐式引用对象:
function method() { console.log(this.data); } function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = method;
解决方案与上面提到的相同:如果可用,使用.bind
将this
显式绑定到特定值
document.body.onclick = this.method.bind(this);
或者通过使用匿名函数作为回调/事件