代码1:

        for (var i=1; i<=5; i++) {            setTimeout(function timer() {              console.log(i);            }, i*1000 );        }

失常状况下,咱们对这段代码行为的预期是别离输入数字1~5,每秒一次,每次一个。
但实际上,这段代码在运行时会以每秒一次的频率输入五次6。

代码2:

        for (var i=1; i<=5; i++) {            (function() {              setTimeout(function timer() {                  console.log(i);              }, i*1000 );            })();        }

后果还是: 以每秒一次的频率输入五次6。
代码3:

        for (var i=1; i<=5; i++) {            (function() {              var j = i;              setTimeout(function timer() {                  console.log(j);              }, j*1000 );            })();        }

后果就失常了:别离输入数字1~5,每秒一次,每次一个

代码4(改良):

        for (var i=1; i<=5; i++) {            (function(j) {              setTimeout(function timer() {                  console.log(j);              }, j*1000 );            })(i);        }

代码4(再改良):

        for (var i=1; i<=5; i++) {            let j = i; // 是的,闭包的块作用域!            setTimeout( function timer() {              console.log(j);            }, j*1000 );        }

代码5(再改良):

        for (let i=1; i<=5; i++) {            setTimeout(function timer() {              console.log(i);            }, i*1000 );        }

阐明:
let申明,能够用来劫持块作用域,并且在这个块作用域中申明一个变量。

块作用域和闭包联手便可天下无敌

知识点起源:

《你不晓得的JavaScript(上卷)》,5.4 循环和闭包