一个循环问题引起的深思

176 阅读2分钟

循环问题

function test() {
    for(var i = 0; i < 5; i++) {
        setTimeout(() => {
            console.log(i);
        }, i * 1000);
    }
}
test();

相信各位前端老司机对这个循环问题的输出都心照不宣了

循环问题输出.png

其实这段代码可以学到的知识点很多:

  • 变量提升
  • 块状作用域
  • 任务队列
  • 闭包

变量提升

变量提升 是个什么东西呢?根据以下代码进行分析

test();
console.log(testVar);
function test() {
    console.log('test function');
}
var testVar = 'testVar';

输出结果:

test function
undefined

在执行过程中,会发现即使test函数 和 testVar变量在执行之后才进行的变量声明,运行却并不会报错,就是因为JS的执行机制具有 变量提升 这一个特点,使用 var 关键字定义的变量或者 函数声明 都会被自动提升到作用域顶部,从而使其可以访问以及执行; 上述代码经过 变量提升 的结果后,模拟的代码 如下:

test = function() {
    console.log('test function');
};
testVar = undefined;
test();
console.log(testVar);
testVar = 'testVar';

所以输出结果为

test function 
undefined

编译与执行

JS代码执行流程.png

在这个过程中,编译阶段将这段代码编译成了两部分

  1. 执行上下文
  2. 可执行代码

其中 执行上下文 中的 变量环境 就完成了 变量提升 这一操作!

  1. 在变量环境中存入test 函数声明
  2. 变量环境中放入testVar 变量并初始化为undefined

可执行代码 在执行阶段对执行上下文的内容进行操作

  1. test函数执行,在变量环境中搜索到,执行!
  2. console.log(testVar) 在变量环境中搜索到testVar变量,变量值为undefined
  3. testVar = 'testVar' 语句执行,变量环境中的testVar变量赋值为'testVar' 执行完毕!

块状作用域

待续!

任务队列

待续!

闭包

待续!