JavaScript经典面试题

    xiaoxiao2022-07-13  138

    for(var i = 1; i <= 3;i++){ setTimeout(function(){ console.log("这是上面的i:"+i) },0) console.log("这是下面的i:"+i) }

    输出: OK!为啥输出结果是这样子的呢?

    所用知识点:作用域,闭包,异步

    相信大家对for循环已经很了解了,应该只是对setTimeout有点陌生

    setTimeout(function(){ console.log(2) },0) console.log(1)

    输出 1,2

    由此可见,我们使用setTimeout的时候是一种异步机制。setTimeout有两个参数,第一个是函数,第二个是执行的时间间隔值,默认毫秒。异步指的是当函数在执行这个事件时,把函数的参数放在事件对列中,等主程序执行完,然后再执行这个事件。体现在我们的例子中,就是当程序执行到setTimeout时,会将setTimeout中的参数放在主程序执行的事件队列里,当主程序执行完毕之后,才会执行setTimeout中的内容。 当setTimeout的时间为0代表等待主程序执行完之后再执行异步的程序,若不为o则代表执行主程序的同时开始计时,等时间到了之后再执行程序。


    接下来分析一下代码运行流程:

    i = 1 console.log("这是下面的i:"+i) // 1 i++ console.log("这是下面的i:"+i) // 2 i++ console.log("这是下面的i:"+i) // 3 i++ console.log("这是上面的i:"+i) // 4 console.log("这是上面的i:"+i) // 4 console.log("这是上面的i:"+i) // 4

    那么到这一步应该对这个理解了吧。 还有一个问题就是作用域。如果我们执行的程序是这样子的

    for(let i = 1; i <= 3;i++){ setTimeout(function(){ console.log("这是上面的i:"+i) },0) console.log("这是下面的i:"+i) }

    输出: 这是下面的i:1 这是下面的i:2 这是下面的i:3 这是上面的i:1 这是上面的i:2 这是上面的i:3

    变量提升:使用var时候声明变量是函数作用域,作用在全局,在预解析时会将变量提升到函数顶部,在这里也就是全局的顶部,而let声明的变量是块级作用域,在预解析时候会把变量提升在for循环的第一行。 代码分析:

    for(let i = 1; i <= 3;i++){ let i = 圆括号中的值 setTimeout(function(){ console.log("这是上面的i:"+i) },0) console.log("这是下面的i:"+i) } // 执行流程 // 每次输出i的值,i都会根据作用域链去找他的值。 // 第一次 let i = 1 setTimeout(function(){ console.log("这是上面的i:"+i) },0) console.log("这是下面的i:"+i) i++ // 第二次 let i = 2 setTimeout(function(){ console.log("这是上面的i:"+i) },0) console.log("这是下面的i:"+i) i++ // 第三次 let i = 3 setTimeout(function(){console.log("这是上面的i:"+i)},0) console.log("这是下面的i:"+i) i++ -------------------- 然后在这里呢,我们会看到setTimeout中的i依次为1,2,3 只是在每次执行的时候都将setTimeout 中的值放在了主程序之后,所以我们会输出1,2,3,1,2,3这样的结果

    关于let和var在for循环中的表现可以参考以下链接:

    https://blog.csdn.net/wlk2064819994/article/details/79772388

    当然如果我们想要让setTimeout中的值先输出也可以,将函数改为立即执行函数

    for(var i = 1; i <= 3;i++){ setTimeout(function(){ console.log("这是上面的i:"+i) }(i),0) // 立即执行函数 console.log("这是下面的i:"+i) }
    最新回复(0)