闭包与ES6的let关键字

18

尝试使用闭包和let在for循环中打印一系列数字:

请考虑以下示例:

  for(var i=1; i<10; i++){      
      setTimeout(function(){
        document.write(i);
      }, 1000);
  }

输出为:

101010101010101010

使用闭包:

  for(var i=1; i<10; i++){    
    (function(x){      
      setTimeout(function(){
        document.write(x);
      }, 1000);      
    })(i);
  }

输出为:

123456789

不使用闭包,仅使用ES6 let:

 for(let i=1; i<10; i++){      
      setTimeout(function(){
        document.write(i);
      }, 1000);
  }

输出为:

123456789

尝试理解在转向ES6时是否仍需要使用IIFE块来使用闭包?

如果我们确实需要在ES6中使用闭包,是否有任何好的示例?


2
这仍然是一个闭包。不同之处在于作用域由块提供,而不是IIFE。 - Bergi
那么,我的问题是我们是否需要使用IIFE块而不是闭包呢?;) :P - Mithun Shreevatsa
JavaScript循环内的闭包 - 简单实用的例子 - Oriol
我不太明白你的问题,难道你的问题不已经表明在使用 let 时不需要 IIFE 吗? - Oriol
1
在这种情况下,它听起来像是const和let会使IIFE模式变得不必要吗?的重复。 - Bergi
这是黄金。我会保存它以备将来参考。 - sg28
4个回答

7
这里有一篇由 Kleo Petrov 提供的好的解释 -
ES5 中,IIFE 是最常用的模式之一,因为函数是声明作用域代码块的唯一方式。在 ES6 中,我们可以使用模块来替代 IIFE: ES6 模块是否使 IIFE 成为过时的模式?
// myModule.js

let counter = 0;

export function increment() {
    counter++;
}    

// logic.js

import {increment} from 'myModule.js';

increment();

在ES6中,唯一需要使用IIFE的情况是立即调用箭头函数,该函数需要多个表达式,例如:

const SENTENCE = 'Hello world, how are you?';
const REVERSE = (() => {
    const array  = [...SENTENCE];
    array.reverse();
    return array.join('');
})();

5

let在变量声明时会将名称绑定到块级作用域中。您可以在标准文档中了解其语义。

如果您有let,请使用它。否则,请使用IIFE或重写代码以避免需要两者之一。


4

使用闭包的一个简单示例是计数器:

function makeCounter() {
  let currentCount = 1;

  return function() { 
    return currentCount++;
  };
}

let counter = makeCounter(); 


console.log( counter() ); // 1
console.log( counter() ); // 2
console.log( counter() ); // 3


1
这似乎并没有真正回答问题。 - Bergi
这只是一个闭环的例子,但并没有回答问题。 - undefined

1
这种情况下,如果您想在每次迭代中重新分配变量的值,则使用新的Es6块作用域确实可以简化操作。
在最新的N. Zachas书籍中有一篇非常好的评论,可在github上找到(整本书都很好,如果您打算将其用作主要参考资料,可能应该购买它)。
至于您的示例,使用新语法可能是新的最佳实践,因为它会产生预期的行为,而旧的for(var i = 0; i < length; i++){}语法则令人困惑。
但请记住,您可能需要使用Babel或Tracer将代码转换为es5。在这种情况下,这些工具模拟块作用域的方式是使用闭包。因此,出于完整性和调试目的,您可能应该了解该模式。

这是一本关于转译的例子,在这里可以找到书中的例子。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接