一道有关settimeout的经典面试题

Posted by Juan on 2017-04-06

回顾下闭包形成的条件:

  • 在函数内部创建新的函数
  • 内部函数访问了父函数的变量

setTimeout中定义的操作,会放在一个FIFO队列中,且需要等待到函数调用栈清空之后才开始依次执行,这些操作进入队列的顺序,则由设定的延迟时间来决定。

面试题

利用闭包,修改下面的代码,让循环输出的结果依次为1, 2, 3, 4, 5

1
2
3
4
5
6
for (var i=1; i<=5; i++) { 
setTimeout( function timer() {
console.log(i);

}, i*1000 );
}

解法1

利用闭包的特性,通过包裹一层自执行函数为闭包的形成提供条件

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

or

1
2
3
4
5
6
7
for (var i=1; i<=5; i++) { 
setTimeout( (function(i) {
return function() {
console.log(i);
}
})(i), i*1000 );
}

解法2

利用setTimeout第三个参数

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

解法3

利用bind方法

1
2
3
4
5
for (var i=1; i<=5; i++) { 
setTimeout(function (i) {
console.log(i);
}.bind(null,i), i*1000 );
}

解法4

利用ES6中的let

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