zoukankan      html  css  js  c++  java
  • JS关于setTimeout()与for(){}循环之间的纠缠不清

    问题写法

    for(var i = 1; i <= 5; i++) {
        setTimeout( function(){
            console.log(i);
        },i*1000);
    }
    console.log(i);
    // 先输出环境运行产生的一个6,每隔1s,再输出一个6,连续输出5个6
    
    • 解析:
      • 此处的i是由var定义在全局作用域内,输出值i属于全局作用域的值
      • setTimeout()函数运行机制是,等全局环境运行完成后,再运行回调函数
      • 因此,i的终值是都是全局变量i的值
      • 因为回调函数并不是随着环境一起运行的,而是等到环境函数运行完成后再集中运行的
      • 因此,五次循环相当于一起执行五次setTimeout()函数
      • 所以累加的秒数就相当于,每隔一秒执行一次

    let定义写法

    for(let i = 1; i <= 5; i++) {
        setTimeout( function(){
            console.log(i);
        },i*1000);
    }
    console.log(i);
    // 先输出i未定义,再每隔1s输出累加值
    
    • 解析:
      • 此处的i是由let定义在块级作用域内,输出值i属于块级作用域的值
      • 因此当i值出现变化时,是属于内部作用域的变化
      • 而setTimeout()函数运行机制是,等环境运行完成后,再运行回调函数
      • 因此,当i值出现变化时,已经没有环境程序在运行了
      • 所以,此时for循环是跟着setTimeout()函数运行的
      • 因此,i的输出值是for循环的累加值

    立即函数写法

    for(var i = 1; i <= 5; i++) {
        (function(i){
            setTimeout( function(){
                console.log(i);
            },i*1000);
        })(i);
    }
    console.log(i);
    // 先输出i未定义,再每隔1s输出累加值
    
    • 解析:
      • 此处的i是由var定义在全局作用域内,输出值i属于全局作用域的值
      • 虽然,setTimeout()函数运行机制是,等全局环境运行完成后,再运行回调函数
      • 但是,每次的for循环运行时,内部的立即函数都会执行
      • 而且,i的值会由形参i传入到setTimeout()函数内部
      • 从而形成关于i的私有作用域
      • 因此此时的setTimeout()函数是和环境程序一起行动的
      • 而最外围的i的输出没有时延,因此会先输出

    闭包函数写法

    for (var i = 1; i <= 5; i++) {
    	setTimeout(function(i) {
    		return function(){
    			console.log(i);
    		}
    	}(i), i*1000);
    }
    console.log(i);
    // 先输出i未定义,再每隔1s输出累加值
    
    • 解析:
      • 此处的i是由var定义在全局作用域内,输出值i属于全局作用域的值
      • setTimeout()函数运行机制是,等全局环境运行完成后,再运行回调函数
      • 而此处的闭包写法,已然将for循环中i的变量值通过形参i保存于return机制中
      • 形成私有作用域
      • 待setTimeout()进行回调函数运行时,i将输出私域内的累加值

    错误写法

    for(var i = 1; i <= 5; i++) {
        setTimeout(function(i){
            console.log(i);
        }(i),i*1000);
    }
    console.log(i);
    
    • 解析:
      • 此处的setTimeout()函数内的回调函数
      • 在主程序运行时,已经随着主程序一起执行完毕
      • 待setTimeout()异步运行时,已无回调函数可用
  • 相关阅读:
    ssh中使用spring的集成quartz 编写定时任务
    ssh只读事务的管理
    ssh2的application.xml配置文件配置详解
    spring中使用 @value 简化配置文件的读取
    【转】Spring Annotation 详解
    ssh之<context:component-scan base-package="com.xx" />
    ssh2学习-applicationContext.xml文件配置-----<context:annotation-config/>详解
    【转】线程同步------java synchronized详解
    java web程序中项目名的更改(http://localhost:8080/)后面的名字
    mysql 5.6 修改root原始密码不为空方法
  • 原文地址:https://www.cnblogs.com/SharkJiao/p/13552430.html
Copyright © 2011-2022 走看看