从闭包返回变量

时间:2011-10-06 23:45:03

标签: javascript closures

如何从闭包中获取返回值?而不是:

this.setCanvas = function(files){
  var numItems = files.length - 1;
  this.items = {};

  var i = 0;
  for(i=0;i<=numItems;i++)
  {
    var file = files[i];
    var reader = new FileReader(); 

    reader.onload = (function(i) { 
      return function(e) { 
        var something = that.whatever();
        items[i] = something;
      }; 
    })(i);  

    reader.readAsDataURL(file);
  }

console.log(items); 
}

我需要定义项目[i]。如果我在闭包之外的console.log items [i]那么它是未定义的。

3 个答案:

答案 0 :(得分:2)

问题不在于闭包; 它是回调。无论需要使用什么,that.whatever的值都需要在中执行回调。

答案 1 :(得分:1)

您可以扩充代码以跟踪加载的文件数量。这样,当加载了最后一个文件时,您可以调用最终的完成处理程序:

  this.setCanvas = function(files) {
    var numItems = files.length - 1;
    var itemsLoaded = 0; // Initialize to zero

    var items = [];

    var i = 0;
    for(i=0;i<=numItems;i++) {

      var file = files[i];
      var reader = new FileReader(); 

      reader.onload = (function(i) { 
        return function(e) { 
          var something = that.whatever();
          items[i] = something;

          if(++itemsLoaded == numItems) {
            // At this point all files will have been loaded.
            allLoaded();
          }
        }; 
      })(i);  

      reader.readAsDataURL(file);
    }

    function allLoaded() {
      // Now we can analyze the results
      console.log(items); 
    }
  }

我还将items更改为Array而不是Object

此外,如果您想更聪明一点,可以递减numItems并检查零,而不是创建新的itemsLoaded变量。

答案 2 :(得分:0)

这里有一些你需要改变的事情。首先将this.items设置为数组。接下来将其分配给self,以便在闭包中引用它。接下来将东西分配给self.items [i]而不是items [i]。最后在console.log中使用this.items

this.setCanvas = function(files){
  var self = this;
  var numItems = files.length - 1;
  this.items = [];

  var i = 0;
  for(i=0;i<=numItems;i++)
  {
    var file = files[i];
    var reader = new FileReader(); 

    reader.onload = (function(i) { 
      return function(e) { 
        var something = that.whatever();
        self.items[i] = something;
      }; 
    })(i);  

    reader.readAsDataURL(file);
  }

    console.log(this.items); 
}