zoukankan      html  css  js  c++  java
  • 解读经典面试题for循环console.log

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


    会打印出5个6,这是why

    因为 for 循环会先执行完(同步优先于异步优先于回调),这时五个 setTimeout 的回调全部塞入了事件队列中,然后 1 秒后一起执行了。
    为什么不是 1 2 3 4 5 ,问题出在作用域上。

    为 setTimeout 的 console.log(i); 的i是 var 定义的,所以是函数级的作用域,不属于 for 循环体,属于 global。
    等到 for 循环结束,i 已经等于 5 了,这个时候再执行 setTimeout 的五个回调函数(参考上面对事件机制的阐述),里面的 console.log(i);
    的 i 去向上找作用域,只能找到 global下 的 i,即 5。所以输出都是 5。

    办法1:人为给 console.log(i); 创造作用域,保存i的值。
    for (var i = 0; i < 5; i++) {
      (function(i){   //立刻执行函数
        setTimeout(function (){
          console.log(i);
         },1000);
      })(i);
    }
    这里用到立刻执行函数。这样 console.log(i); 中的i就保存在每一次循环生成的立刻执行函数中的作用域里了。
     
    办法2
    for (let i = 0; i < 5; i++) {   //let 代替 var
      setTimeout(function (){
        console.log(i);
       },1000);
    }
    let 为代码块的作用域,所以每一次 for 循环,console.log(i); 都引用到 for 代码块作用域下的i,因为这样被引用,所以 for 循环结束后,这些作用域在 setTimeout 未执行前都不会被释放。
  • 相关阅读:
    迭代器设计模式
    python中的turtle库绘制图形
    Tesseract-OCR4.0识别中文与训练字库实例
    java图片处理
    Tess4J OCR简单使用教程
    C++ 排列最优解算法思想
    Swing使用JavaFXweb组件
    java专业术语
    java的分数类
    System Rules 更好的测试
  • 原文地址:https://www.cnblogs.com/myfirstboke/p/10365476.html
Copyright © 2011-2022 走看看