javascript 在for in语句中声明变量的两种方式有什么区别?

km0tfn4u  于 2023-05-21  发布在  Java
关注(0)|答案(1)|浏览(128)

如果我使用for in,我总是使用const来声明变量

const array = ["a","b","c"]

for (const value in array) {
  console.log(value);
}

但另一种方法是使用全局作用域变量

let value
const array = ["a","b","c"]

for (value in array) {
  console.log(value);
}

结果是一样的,但我不知道哪种方法更好。你能解释一下上述两种方法在内存或成本方面的区别吗?
结果是一样的,但我不知道哪种方法更好。你能解释一下上述两种方法在内存或其他成本方面的区别吗?

kgsdhlau

kgsdhlau1#

首先,使用for...in循环来迭代数组shouldn't be done的索引,而不是使用常规的for循环。如果要迭代数组的值,请使用类似for...of.forEach()循环的方法。
你的两个例子之间的第一个区别可能是最明显的一个。在第一个例子中,你已经用const声明了你的变量,所以在for循环体中将它赋给一个不同的值是不可能的。而对于let,如果需要,可以重新分配它。
例如,如果您尝试重新分配value,下面的代码将抛出错误

const array = ["a","b","c"];
for (const value of array) { // updated to for...of loop
  value = 1; // 🟥 this will throw!
  console.log(value);
}

而下面的代码将正常工作:

let value
const array = ["a","b","c"];
for (value of array) {
  value = 1; // 🟩 works perfectly fine
  console.log(value);
}

这两个示例之间的其他差异与value变量的作用域有关。在第一个例子中,为数组的每次迭代和for循环体的调用创建一个新的value绑定,这意味着为每次迭代创建独立的value变量,并将其作用域限制在当前块。这意味着value不能在for循环之外访问。在第二个代码块中,let value在for循环之外声明,因此自然可以在for循环之外访问它。

const array = ["a","b","c"];
for (const value of array) {
  console.log(value);
}
console.log(value); // 🟥 this will throw!

与在循环外声明的value相比:

let value;
const array = ["a","b","c"];
for (value of array) {
  console.log(value);
}
console.log(value); // 🟩 this will work and log "c"

除此之外,在for循环外声明value意味着在for循环的每次迭代中都会更新您声明的相同全局value变量,从而导致每次调用for循环体时共享相同的变量。如果您有一个closure/function inside of your loop,则可以看到这一点的含义。
下面的日志记录了abc,因为当在循环中声明setTimeout()回调函数时,它使用了为value创建的唯一绑定,用于循环的特定迭代:

const array = ["a","b","c"];
for (const value of array) {
  setTimeout(() => {
    console.log(value);
  }, 500);
}
// logs:
// a
// b
// c

这记录了ccc,因为当回调函数被创建时,它使用了value的全局共享值,当setTimeout()执行时,for循环已经完成(所以此时值将是"c"):

let value;
const array = ["a","b","c"];
for (value of array) {
  setTimeout(() => {
    console.log(value);
  }, 500);
}
// logs:
// c
// c
// c

由于在for循环语句中直接使用const(或let)需要为循环的每次调用创建一个新的绑定,因此可以说它占用了更多的内存,但这一小部分应该可以忽略不计,不必担心。此外,JavaScript引擎很可能会为此进行优化,因此我建议直接在循环语句中声明变量,因为它将最大限度地减少将变量泄漏到for循环外部的周围范围中的问题。

相关问题