美文网首页
一个闭包笔试题

一个闭包笔试题

作者: 爱楚楚真是太好了 | 来源:发表于2019-06-17 16:46 被阅读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

    相关文章

      网友评论

          本文标题:一个闭包笔试题

          本文链接:https://www.haomeiwen.com/subject/lvxzfctx.html