首页 > 解决方案 > 在具有多个循环的函数中使用 var?

问题描述

引用JavaScript: The Definitive Guide一书

与用let声明的变量不同,用 多次声明同一个变量是合法的var。并且因为var变量具有函数作用域而不是块作用域,所以这种重新声明实际上很常见。该变量i经常用于整数值,尤其是作为 for 循环的索引变量。在具有多个 for 循环的函数中,通常每个循环都开始for(var i = 0;.... 因为var不将这些变量限定为循环体,所以这些循环中的每一个都(无害地)重新声明和重新初始化相同的变量。

我无法理解这一段的意思。首先,我假设以下内容不适用于不迭代的第二个循环,因为i它是函数作用域:

(function foo() {
    for (let i = 0; i < 2; i++) {
        console.log(i);
    }
    for (let i = 0; i < 2; i++) {
        console.log(i);
    }
})();

但它打印

0
1
0
1

然后我假设这会打印出来0 0 1 1 0 1,但事实并非如此:

(function foo() {
    for (var i = 0; i < 2; i++) {
        console.log(i);
        for (var i = 0; i < 2; i++) {
            console.log(i);
        }
    }
})();

有人可以帮我理解什么是

在多个 for 循环的函数中,var可以在每个循环中无害地使用

和它有什么不同let

对我来说,它看起来正好相反(这也很令人困惑)let可以在具有多个循环的函数中无害地使用:

(function foo() {
    for (let i = 0; i < 2; i++) {
        console.log(i);
        for (let i = 0; i < 2; i++) {
            console.log(i);
        }
    }
})();

印刷:

0
0
1
1
0
1

标签: javascriptvarlet

解决方案


let禁止在同一范围内重新声明变量,如下所示:

let foo = 10;
let foo = 20;

var但是,变量可以是:

var foo = 10;
var foo = 20;
console.log('ok');

在您的第一个片段中,let在循环头中声明的变量for只存在于循环内;它们是块作用域,而不是外部块或函数的作用域:

(function foo() {
    for (let i = 0; i < 2; i++) {
        // console.log(i);
    }
    for (let i = 0; i < 2; i++) {
        // console.log(i);
    }
    // doesn't exist out here:
    console.log(i);
})();

上面的s 在两个不同let i的范围内创建了 s ,这就是它不被禁止的原因。相似地:i

(function foo() {
    {
        let i = 10;
    }
    {
        let i = 20;
    }
    console.log('OK up until here');
    // doesn't exist out here:
    console.log(i);
})();

vars,相比之下,具有函数范围,而不是块范围 - 使用您var的循环版本,因为只有一个函数,这个:

(function foo() {
    for (var i = 0; i < 2; i++) {
        console.log(i);
        for (var i = 0; i < 2; i++) {
            console.log(i);
        }
    }
})();

相当于

(function foo() {
    var i; // the `i` variable exists at this level
    for (i = 0; i < 2; i++) {
        console.log(i);
        for (i = 0; i < 2; i++) {
            console.log(i);
        }
    }
})();

然后我假设这会打印 0 0 1 1 0 1,但事实并非如此:

i在每个循环开始时初始化为零。

第一个循环在函数开始时开始一次。

第二个循环在 logging 之后开始i,在外循环的每次迭代中。

(function foo() {
    for (var i = 0; i < 2; i++) {
        console.log(i);
        for (var i = 0; i < 2; i++) {
            console.log(i);
        }
    }
})();
  • 外循环初始化:0分配给i
  • 0 被记录
  • 内循环初始化:0分配给i
  • 0 被记录
  • 内循环将 i 递增到 1 并重新开始
  • 内循环:1 被记录
  • 内部循环将 i 增加到 2 并中断,因为 i < 2 不再满足
  • 外循环将 i 增加到 3 并中断,因为 i < 2 不再满足

所以你被0 0 1登录了。

这篇文章可能是什么意思

在多个 for 循环的函数中,可以在每个循环中无害地使用 var

如果两个循环都在函数的同一级别上,它可以工作,例如

for (...) {
}
for (...) {
}

如果两个循环都使用相同的变量,它肯定不适用于嵌套循环,因为只有一个i变量,而不是每个循环一个变量。

其中 let 可以在具有多个循环的函数中无害地使用:

对于嵌套循环,是的,因为声明的变量let对于每个循环都是唯一的,而不是在整个包含函数中共享。


推荐阅读