我有一个注册事件处理程序的构造函数:
函数MyConstructor(数据,传输){this.data=数据;transport.on('数据',函数(){警报(this.data);});}//模拟传输对象var传输={on:函数(事件,回调){setTimeout(回调,1000);}};//称为var obj=新MyConstructor('o',传输);
但是,我无法访问回调中创建的对象的数据属性。看起来这不是指创建的对象,而是指另一个对象。
我还尝试使用对象方法而不是匿名函数:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
但它表现出相同的问题。
如何访问正确的对象?
问题围绕着this关键字在JavaScript中的行为。这表现如下不同,
其值通常由函数执行上下文确定。在全局范围中,这是指全局对象(窗口对象)。如果为任何函数启用了严格模式,则其值将是未定义的,因为在严格模式中,全局对象是指未定义的窗口对象。位于点之前的对象是this关键字将绑定到的对象。我们可以使用call()、bind()和apply()显式设置此值当使用new关键字(构造函数)时,它将绑定到正在创建的新对象。箭头函数不绑定此 — 相反,这是在词汇上绑定的(即,基于原始上下文)
正如大多数答案所建议的那样,我们可以使用arrow函数或bind()方法或Self var。我将引用GoogleJavaScript风格指南中关于lambdas(arrow函数)的一点
更喜欢使用箭头函数而不是f.bind(this),尤其是在goog.绑定(f,this)。避免写入常量self=this。箭头功能对于有时意外传递的回调特别有用其他参数。
谷歌明确建议使用lambdas,而不是bind或const self=this
因此,最好的解决方案是使用如下lambdas,
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
参考文献:
https://medium.com/tech-tajawal/javascript-this-4-rules-7354abdb274c箭头函数与绑定
以下是访问子上下文中的父上下文的几种方法-
您可以使用bind()函数。在另一个变量中存储对context/this的引用(参见下面的示例)。使用ES6箭头功能。改变代码、功能设计和架构——为此,您应该能够控制JavaScript中的设计模式。
1.使用bind()函数
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', ( function () {
alert(this.data);
}).bind(this) );
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
如果您正在使用Undercore.js-http://underscorejs.org/#bind
transport.on('data', _.bind(function () {
alert(this.data);
}, this));
2.在另一个变量中存储对context/this的引用
function MyConstructor(data, transport) {
var self = this;
this.data = data;
transport.on('data', function() {
alert(self.data);
});
}
3.箭头功能
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}