【问题标题】:Javascript - "this" scope issue fixJavascript - “this”范围问题修复
【发布时间】:2014-02-26 17:05:36
【问题描述】:

我一直在玩 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);

这给了我“Ann Other”。完美的!而如果我取消注释“this.fullName”行并注释掉“clientData.fullName”,我会得到“Not Set”,window.fullName 会包含“Ann Other”(“this”的传统范围问题是附加到全局窗口)。

当然,这是一个原始示例,但这是不好的做法吗?现在这意味着我在访问回调函数中的本地属性时从来没有遇到过问题。我也不需要使用“调用”或“应用”函数并传入对象引用,这样我就可以在正确的范围内访问“this.propertyName”。任何答案将不胜感激。

【问题讨论】:

    标签: javascript callback scope this


    【解决方案1】:

    是的,这是一种不好的做法。如果支持,请使用Function.prototype.bind

    getUserInput("Ann", "Other", clientData.setUserName.bind(clientData));
    

    (当您有原型可供使用时,这会减少冗余。)

    或者,万无一失但不那么漂亮的解决方案:

    getUserInput("Ann", "Other", function(firstName, lastName) {
        clientData.setUserName(firstName, lastName);
    });
    

    奖励 ES6 模式(但如果你有 ES6,为什么不使用bind?)

    getUserInput("Ann", "Other", (...args) => clientData.setUserName(...args));
    

    【讨论】:

      【解决方案2】:

      在其方法中引用对象的名称绝对不是一个好习惯,因为如果您更改对象的名称,您应该更改方法的实现。

      我建议你使用:

       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);
      

      【讨论】:

      • “数据”参数确实不是真的需要吗?作为参数 param 为 setUserName 函数提供值?
      • 是的,我喜欢 bind 方法,它很有意义。我只是好奇,因为我偶然发现的东西工作得很好,并且明白如果方法名称发生变化,我将不得不重命名事物(在某些方面不太可能但很容易改变)。我也很感激我可以使用“应用”或“调用”并传入上下文对象。还有另一种访问属性并避免设置“self = this;”属性的范围问题的方法。然后通过 object.self.propertyName 访问属性。我只是很好奇,因为它可能是一个非常容易被误解的领域。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      • 1970-01-01
      相关资源
      最近更新 更多