一个闭包笔试题

2019-06-17  本文已影响0人  爱楚楚真是太好了

预备知识:
使用setTimeout会生成一种特殊的队列结构,而这个队列执行的时间,需要等待到函数调用栈清空之后才开始执行。即所有可执行代码执行完毕之后,才会开始执行由setTimeout定义的操作。而这些操作进入队列的顺序,则由设定的延迟时间来决定。

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

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

根据setTimeout定义的操作在函数调用栈清空之后才会执行的特点,for循环里定义了5个setTimeout操作。而当这些操作开始执行时,for循环的i值,已经先一步变成了6。因此输出结果总为6。而我们想要让输出结果依次执行,我们就必须借助闭包的特性,每次循环时,将i值保存在一个闭包中,当setTimeout中定义的操作执行时,则访问对应闭包保存的i值即可。
解法1:

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

解法2:

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

解法3:

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

巩固列子:

setTimeout(function() {
    console.log(a);
}, 0);
 
var a = 10;
 
console.log(b);
console.log(fn);
 
var b = 20;
 
function fn() {
    setTimeout(function() {
        console.log('setTImeout 10ms.');
    }, 10);
}
 
fn.toString = function() {
    return 30;
}
 
console.log(fn);
 
setTimeout(function() {
    console.log('setTimeout 20ms.');
}, 20);
 
fn();
599584-bc54089aededce6f.png

先执行完除setTimeout以外的所有可执行代码,然后在根据setTimeout设置的延时时间去决定执行顺序,这里需要注意的是,当执行fn()时,发现新增一个setTimeout,然后再根据延迟时间来决定执行顺序。

摘自:https://www.jianshu.com/p/9b4a54a98660

上一篇 下一篇

猜你喜欢

热点阅读