如何在对象构造期间使用异步生成的值分配属性?

时间:2015-01-21 21:13:09

标签: javascript asynchronous constructor prototype

如何在对象构造期间使用异步生成的值分配属性?

我正在尝试在构造期间将属性分配给需要通过AJAX检索的对象:

//define module prototype
Library.Module = function () {
    this.resources = {};
    for (var i = 0; i < arguments.length; i++) {

        // assume that Library.require makes a request and 
        // then executes this callback
        Library.require(arguments[i], function (resource) {

            // ! the problem seems to be that 'this' is undefined 
            // in the scope of the callback
            this.resources[resource.location] = resource;
        });
    }
};

我认为这段代码的意图相当明确 - 问题是this似乎在回调函数的范围内未定义。

1 个答案:

答案 0 :(得分:1)

如下面的文章https://blog.engineyard.com/2015/mastering-this-in-javascript和后面的评论中所述,可能的解决方案是将其存储在范围中较高的变量中,以便在回调中使用它。

因此可能的解决办法是:

Library.Module = function () {
    var _this = this;

    _this.resources = {};
    for (var i = 0; i < arguments.length; i++) {

      // assume that Library.require makes a request and 
      // then executes this callback
      Library.require(arguments[i], function (resource) {

        _this.resources[resource.location] = resource;
      });
   }
};

引用文章中的有用摘录:

  

在回调中管理

     

就是这样:这是设置函数的四种方法。   这四条规则并不难记,但有一个共同点   你应该知道的陷阱。我在谈论回调。这很简单   写一个回调,甚至不知道它,就像在setTimeout中一样:

setTimeout(function() {
    $(‘button’).addClass(‘red’);
}, 1000);
     

setTimeout函数接受回调,但因为它没有使用   设置上下文的四个规则之一,默认为全局   窗口对象。在上面的例子中这很好,但是变成了一个bug   像这样的代码:

$('button').on('click', function() {
    setTimeout(function() {
        // Uh oh! `this` is the global object!
        $(this).addClass('clicked');
    }, 1000); 
});
     

我们期望$(this)引用被点击的按钮,但是   它没有,因为它默认为全局窗口对象。单程   解决这个问题的方法是将我们想要的值存储在本地   变量,然后简单地在子范围中使用该变量:

$('button').on('click', function() {
    var _this = this;
    setTimeout(function() {
        $(_this).addClass('clicked'); // All better
    }, 1000); 
});
     

当然,有很多方法可以完成同样的事情。你可以   使用.bind(),. call()或许多其他选项。选择有效的方法   最适合每个人的情况。