在错误的背景下依赖this
是一个常见的陷阱。一个人为的例子:
function SomeClass() {
this.prop = 42;
document.body.addEventListener('click', function() {
alert(this.prop); // will be undefined
});
}
new SomeClass();
解决此问题的一种方法是使用bind
(或call
或apply
),例如:
function SomeClass() {
this.prop = 42;
document.body.addEventListener('click', (function() {
alert(this.prop); // works
}).bind(this));
}
new SomeClass();
另一种选择是通过关闭提供对this
的引用,通常是_this
或self
:
function SomeClass() {
var _this = this;
this.prop = 42;
document.body.addEventListener('click', function() {
alert(_this.prop); // works
});
}
new SomeClass();
我更喜欢后一种方法,因为我可以声明它一次而不是用bind()
包装大量函数,而嵌套回调(我知道它们不是理想的,但在野外看到)变得更简单。但我有一种潜在的怀疑,即a)有这种方法的问题,或者b)我必须这样做或bind
首先意味着我做错了。有什么想法吗?
答案 0 :(得分:3)
您解决此问题的方法"没关系:
function SomeClass() {
this.prop = 42;
document.body.addEventListener('click', (function() {
alert(this.prop); // works
}).bind(this));
}
new SomeClass();
如果你发现你需要这样做,你真的没有做错任何事情,但根据上下文,如果你担心性能,也许你不想创建新的功能(这就是.bind内部对更改此)
您可以使用范围变量,而不是进行绑定,而不是第二个示例:
function SomeClass() {
var _this = this;
this.prop = 42;
document.body.addEventListener('click', function() {
alert(_this.prop); // works
});
}
new SomeClass();
这里唯一剩下的问题是关于代码可读性,但我的问题是关于品味,这就是我要为这个特殊情况做的事情
function SomeClass() {
var prop = 42;
document.body.addEventListener('click', function() {
alert(prop); // works
});
}
new SomeClass();
我只是提高了可读性,可能还有一点性能,但我并不认为这是"方式"为了做到这一点,我试图说你应该知道如何使用词法作用域和闭包并使用(或不使用)你认为必须的地方(当然,这取决于背景)
编辑:等等!我分配了this.prop = 42因为我需要公开属性 在这种情况下,我认为设计PoV的最佳实践是通过getter公开它:
function SomeClass() {
var prop = 42;
document.body.addEventListener('click', function() {
alert(prop); // works
});
this.getProp = function() {
return prop;
};
this.setProp = function(newValue) { // prop is supposed to be modifiable ?
prop = newValue;
};
}
new SomeClass();
关于设计的另一个侧面说明与"这个"问题是,与班级中的全局对象进行交互并不合适,我会这样做:
function SomeClass(receiver) {
var prop = 42;
receiver.addEventListener('click', function() {
alert(prop); // works
});
}
new SomeClass(document.body);
答案 1 :(得分:2)
这种方法有问题吗?
不,没关系。我甚至认为,与bind
(及其ES3不支持)相比,问题更少。有时看到的陷阱是忘记var
(并且如果不是严格模式则引入全局变量),但如果你理解闭包可能不再是问题。
或者我必须这样做或首先绑定的事实意味着我做错了。
不,这就是使用this
的调用方法在JavaScript中的工作方式。我并不是说错误的设计不能异常频繁地使用self
/ bind
,但好的设计也包含这种模式。