JS基础 - for 循环

for 循环的基础知识点

for 循环的执行机制

for 循环内含有三个语句 for( 语句1,语句2,语句3 ){ 自定义函数 }

  • 第一次循环:

    先执行第一个初始化语句,再执行第二个判断语句,如果判断符合则执行自定义函数,如果判断不符合则停止执行。

    举个例子:

    for (var a = 0; a < 5; a++) {
        console.log(a);
    }
    

    上述代码的执行顺序:

    • var a = 0;
    • a < 5
    • console.log(a)
    • a++
  • 之后的循环:

    先执行第二个判断语句,对上一次执行第三个语句的结果进行判断(这里是 js 引擎底层对值进行了记忆),如果判断符合则执行自定义函数,如果判断不符合则停止执行。

for 循环中 var 和 let 的区别

for 循环中对初始化语句只会执行一次,先看个例子:

const a = [];
for (var i = 0; i < 5; i++) {
    a[i] = () =>{
        console.log(i)
    }
}

a[2](); // 5

根据上述的执行机制可以看出:当前 a 数组的长度是 5, i 的值为 5

当我们取 a[2] 时返回的不是 2 而是 5,说明 for 循环内的第三个语句其实都是在修改同一个变量 i

需要注意的是,上面赋给数组 a 的是一个函数,执行函数的时候才会去读取变量 i ,如果把上面的代码修改一下,直接将变量 i 赋值给数组 a,因为数字不是引用类型,所以得到的数组 a 为 [0,1,2,3,4]

const a = [];
for (var i = 0; i < 5; i++) {
    a[i] = i;
}

a[2]; // 2

回到最初的代码,如果把 var 替换成 let:

const a = [];
for (let i = 0; i < 5; i++) {
    a[i] = () =>{
        console.log(i)
    }
}

a[2](); // 2

这是能够打印出预期的结果,那么同样是执行一次初始化语句,为什么 let 能够保持 i 的值呢?是因为 Js 引擎在 for 循环到 let 初始化变量时,会生成多个块级作用域,这些块级作用域中的值互不影响,所以能够保持各自独立的值。

现在在 for 循环之后添加一个 console 语句:

for (var i = 0; i < 5; i++) {
    // whatever
}
console.log( i ) // 5
for (let i = 0; i < 5; i++) {
    // whatever
}
console.log( i ) // ReferenceError: i is not defined

原因也很好理解:var 存在着变量提升,所以使用 var 来初始化时,后续的代码也能够访问到初始化的变量。

如果将 let 从语句1中提出来,会是什么样的:

const a = [];
let i = 0;
for ( ;i < 5; i++) {
    a[i] = () =>{
        console.log(i)
    }
}

a[2](); // 5

因为此时 let 已经不受 for 循环的控制了,无法生成多个块级作用域,所以与 var 的效果一致。

在 for 循环中改进 var

使用闭包可以让 var 声明达到与 let 一致的效果,具体的解释在《理解闭包》文章中有说明。

for (var i = 0; i < 5; i++) {
    (function(n){
        setTimeout(() => console.log(n), 1000)
    })(i)
} // 0 1 2 3 4

for 循环遇到定时器

将上面的代码稍微变动一下:

for (var i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 1000)
} // 5 5 5 5 5
for (let i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 1000)
} // 0 1 2 3 4

其实和上述的原理是一致的,var 生成了一个公用的变量,而 let 生成了多个独立的块级作用域。

其它循环方法

除了 for 循环外,还有 whiledo...while方法可以实现循环,他们两者的区别就在于 while 先判断条件后执行,do…while 先执行后判断条件:

do
  statement
while (expression);
// or
do {
  statement
} while (expression);

与 for 循环相比 while 循环增加了 continue 方法来中止本轮循环,但它们都可以使用 break 方法来跳出循环:

var i = 0;
while (i < 10){
  i++;
  if (i%2 === 0) continue;
  console.log(i);
} // 1,3,5,7,9
for (var i = 0; i < 5; i++) {
  console.log(i);
  if (i === 3) break;
} // 0,1,2,3
作者

BiteByte

发布于

2020-08-31

更新于

2024-01-11

许可协议