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()异步运行时,已无回调函数可用
  • 相关阅读:
    linux MySQL 初始化数据库
    linux 建立 MySQL 账号
    linux MySQL 安装
    Background-Size
    .net文件压缩和解压及中文文件夹名称乱码问题
    C# 浅拷贝与深拷贝区别
    移动端手势库hammerJS 2.0.4官方文档翻译
    期待已久的2012年度最佳jQuery插件揭晓
    Hammer.js
    jQuery Validate验证框架详解
  • 原文地址:https://www.cnblogs.com/SharkJiao/p/13552430.html
Copyright © 2011-2022 走看看