我一直在玩一些Javascript回调并了解“this”的范围问题以及如何通过使用“call”或“apply”并传入对象引用来消除它。
但是,我发现了一些东西,我想知道以下是不好的做法?因为它通过纯粹使用对象名称而不是“this”来消除范围问题。假设我有一个具有回调功能,例如:
function getUserInput(firstName, lastName, callback) {
callback(firstName, lastName);
}
这样的对象:
var clientData = {
id: 1,
fullName: "Not Set",
setUserName: function (firstName, lastName) {
//this.fullName = firstName + " " + lastName;
clientData.fullName = firstName + " " + lastName;
}
}
要执行并查看代码的输出,请执行以下操作:
getUserInput("Ann", "Other", clientData.setUserName);
console.log(clientData.fullName);
这给了我“安其他”。完善!然而,如果我取消注释“this.fullName”行并注释掉“clientData.fullName”,我将得到“未设置”并且window.fullName将包含“Ann Other”(传统的“this”范围问题是附在全球窗口上。)
当然,这是一个原始的例子,但这是不好的做法?现在它现在意味着我从来没有在回调函数中访问本地属性的问题。我也不需要使用“call”或“apply”函数并传入对象引用,以便我可以在正确的范围内访问“this.propertyName”。任何答案都将不胜感激。
答案 0 :(得分:3)
是的,这是一种不好的做法。如果有支持,请使用Function.prototype.bind
:
getUserInput("Ann", "Other", clientData.setUserName.bind(clientData));
(如果你有一个原型可以解决这个问题,那就不那么多了。)
或者,这是一个万无一失但却不那么漂亮的解决方案:
getUserInput("Ann", "Other", function(firstName, lastName) {
clientData.setUserName(firstName, lastName);
});
Bonus ES6模式(但如果您有ES6,为什么不使用bind
?)
getUserInput("Ann", "Other", (...args) => clientData.setUserName(...args));
答案 1 :(得分:0)
在其方法中引用对象的名称绝对不是一个好习惯,因为如果更改对象的名称,则应更改方法的实现。
我建议您使用:
getUserInput("Ann", "Other", clientData.setUserName.bind(clientData));
console.log(clientData.fullName);
问题发生的原因是您在没有callback(firstName, lastName);
运算符的情况下调用回调.
,该运算符将方法调用与特定上下文相关联。
bind
是ES5的一部分,如果您正在寻找更广泛的浏览器兼容性,您可以:
getUserInput("Ann", "Other", function (data) {
clientData.setUserName.apply(clientData, arguments);
});
console.log(clientData.fullName);