Javascript - “此”范围问题修复

时间:2014-02-26 17:05:36

标签: javascript callback scope this

我一直在玩一些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”。任何答案都将不胜感激。

2 个答案:

答案 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);
相关问题