javascript兼容问题 : let降级到var 遇到的闭包问题的解决方法

我用  for(let x in y) 循环一个图片元素数组。

for (let x in arr) {
  arr[x].onload = function(){ /* ... */ }  
}

这样写是没有问题的,因为:

for (let x...)的循环在每次迭代时都为x创建新的绑定。

...

在ES标准中,有一段是关于CreatePerIterationEnvironment,也就是for语句每次循环所要建立环境的步骤,里面有提及有关词法环境的相关步骤(LexicalEnvironment),这与使用let时会有关。所以,如果你使用了let而不是var,let的变量除了作用域是在for区块中,而且会为每次循环执行建立新的词法环境(LexicalEnvironment),拷贝所有的变量名称与值到下个循环执行。

...

但是 用 var 就不行了,因为运行环境没有更新,所以 onload 拿到的 [i] 每次都是最后一位。

相当于:

// 不需要加区块符,因为区块也不会影响
var i;
i = 0;
if (i < 10)
    setTimeout(()=>console.log("i:",i), 1000);
    i++;
    if (i < 10)
        setTimeout(()=>console.log("i:",i), 1000);
        i++;
//...

拿怎么办呢?

在我一筹莫展的时候。 Babel 给了我答案。

原来的代码:

// _this : this(vue实例)
for (let i in img_arr) {
  img_arr[i].onload = function () {
    origin_size_arr[i] = {
       this.width,
      height: this.height,
    }
    if (_this.img_calc_count === (img_arr.length - 1)) {      
      _this.waterFullBFunc()
    } else {
      _this.img_calc_count++
    }
  }
}

Babel 降级之后:

var _loop = function _loop(i) {
  img_arr[i].onload = function () {
    origin_size_arr[i] = {
       this.width,
      height: this.height
    };

    if (_this.img_calc_count === img_arr.length - 1) {
      _this.waterFullBFunc();
    } else {
      _this.img_calc_count++;
    }
  };
};

// _this : this(vue实例)
for (var i in img_arr) {
  _loop(i);
}

以上。

参考:

怎么理解for循环中用let声明的迭代变量每次是新的变量?

Babel 中文网

原文地址:https://www.cnblogs.com/foxcharon/p/11069333.html