for 循环作用域问题

来源:互联网 发布:湖南干部教育网络app 编辑:程序博客网 时间:2024/05/22 09:47

For 循环作用域问题

for 循环简介

for 是一种前测试循环语句,但它具有在执行循环之前初始化变量和定义循环后要执行代码的能力,for 语句对常用的循环模式做了一些简化,大部分的循环都具有特定的计数器变量,循环开始之前要初始化这个变量,然后每次循环都要检测一下他的值,最后计数器变量做自增操作,在这一类循环中,计数器的三个关键操作是初始化、检测和更新。for 语句就将这三步操作明确声明为循环语法的一部分,各自使用一个表达式来表示

    for(initialize; test; increment) {        /*            initialize: 初始化操作            test: 循环条件判断            increment: 计数器变量的更新        */    }

initialize; test; increment 放在循环的第一行会更容易理解 for 循环正在做什么,而且也可以防止忘记初始化或者递增计数器变量

  • initialize 表达式只在循环开始前执行一次,初始化表达式应当具有副作用(通常是一个赋值语句)
  • 每次循环执行之前都会执行 test 表达式,并判断表达式的结果来决定是否执行循环体
  • 如果 test 执行结果为真值,则最后执行 increment 表达式,他也须要具有副作用

2. for 循环的作用域问题

  1. for 循环的 initialize 初始化操作部分使用 var 关键字来声明变量时:
    var arr = [];    for (var i = 0; i < 10; i++) {        arr[i] = function () {            console.log(i);        }    }    console.log(i); // 10     arr[6](); // 10
  • var 声明的变量不存在块级作用域,因此在循环内部定义的变量也可以在外部访问
  • 在 javascript 中 for 循环并不是一个函数体,不存在相应的函数作用域,在 for 循环中定义的变量所处的作用域就是 for 循环所在作用域,也就是说通过 var i = 0; 声明的变量 i 所在的作用域与 arr 同一个级别,每次循环结束时 i++ 作用的也是同一个 i
  • 执行 arr[6]() 时,函数需要用到变量 i, 首先会在函数定义的上下文中查找变量 i ,同样由于 for 循环不是函数体,没有相应的函数作用域,所以 查找到的 i 所在的作用域还是与 arr 同一级别的那个,这个时候 i 经过循环多次的更新,已经是最终的结果 10
  1. for 循环的 initialize 初始化操作部分使用 let 关键字来声明变量时:
    let arr = [];    for (let i = 0; i < 10; i++) {        arr[i] = function () {            console.log(i);        }    }    // console.log(i); // Uncaught ReferenceError: i is not defined    arr[6](); // 6
  • let 是 es6 新增的命令,用来声明变量,用法类似 var, 但是所声明的变量只在 let 命令所在的代码块内有效,for 循环括号内声明的 变量只在循环内有效,因此循环外部不能访问
  • for 循环中如果用 initialize 部分使用 let 初始化,那么这个 for 循环中,设置循环变量的部分(for 后边的()内)是一个父作用域,循环体(for 后边 {}内)内部是一个子作用域。
  • 每次循环 javascript 都会为循环体创建独立的执行上下文,而且本轮循环所对应的 i 值,都是通过 javascript 引擎将记录的上一轮循环的 i 值计算后得出的,但是变量 i 是用 let 声明的,只在当前轮循环有效
  • 执行 arr[6]() 时,函数需要用到变量 i, 首先会在函数定义的上下文中查找变量 i ,也就是函数定义所在的块级作用域中 变量 i 的值。

参考

  • ECMAScript 6 入门
  • JS 引擎如何实现 for (let i;…) { } 写法中每次循环绑定不同的循环变量 i?
原创粉丝点击