( for... in ) 和 ( for... of ) 语句之间有什么区别?

IT技术 javascript arrays for-loop object
2021-01-23 10:30:28

我知道什么是for... in循环(它遍历键),但我for... of第一次听说过(它遍历值)。

我对for... of循环感到困惑

var arr = [3, 5, 7];
arr.foo = "hello";
    
for (var i in arr) {
  console.log(i); // logs "0", "1", "2", "foo"
}
    
for (var i of arr) {
  console.log(i); // logs "3", "5", "7"
  // it doesn't log "3", "5", "7", "hello"
}

我知道for... of迭代属性值。那为什么它不记录"3", "5", "7", "hello"而不是记录"3", "5", "7"

for... in循环遍历每个键 ( "0", "1", "2", "foo") 并且还遍历foo键不同, thefor... of 遍历foo属性的值,即"hello"为什么会这样?

在这里我控制台for... of循环。它应该记录,"3", "5", "7","hello"但它会记录"3", "5", "7"为什么?

示例链接

6个回答

for in 循环对象的可枚举属性名称。

for of(ES6 中的新功能)确实使用了特定对象的迭代器并循环遍历由此生成的值。

在您的示例中,数组迭代器确实产生数组中的所有值(忽略非索引属性)。

助记符:'o'f -> 不是 'o'bjects,'i'n -> 不是 'i'terables
2021-03-22 10:30:28
另一个助记符:::for... of数组 :: 数组总是有长度的,所以你可以认为for.. [nth element] of.. [q elements]
2021-03-30 10:30:28
for ... of 在 ES6 中标准化。
2021-04-06 10:30:28
in给你索引。这足以记住差异。如果你在其他方面应用逻辑。
2021-04-06 10:30:28
另一个助记符... for..in..keys=== 外键 ===for...in用于键!因此,for...of用于值。
2021-04-09 10:30:28

我在Iterators and Generators找到了一个完整的答案(虽然它是针对 TypeScript 的,但对于 JavaScript 也是如此)

无论for..offor..in语句叠代列表; 迭代的值虽然不同,但for..in返回正在迭代的对象上的键列表,而for..of返回正在迭代的对象的数字属性的值列表。

这是一个演示这种区别的示例:

let list = [4, 5, 6];

for (let i in list) {
   console.log(i); // "0", "1", "2",
}

for (let i of list) {
   console.log(i); // "4", "5", "6"
}

另一个区别是for..in对任何对象进行操作;它用作检查此对象上的属性的一种方式。for..of另一方面,主要对可迭代对象的值感兴趣。内置对象MapSet实现Symbol.iterator允许访问存储值的属性。

let pets = new Set(["Cat", "Dog", "Hamster"]);
pets["species"] = "mammals";

for (let pet in pets) {
   console.log(pet); // "species"
}

for (let pet of pets) {
    console.log(pet); // "Cat", "Dog", "Hamster"
}
此外,调用类似 for(let i of {}) { console.log(i); 会抛出 TypeError: VM391:1 Uncaught TypeError: {} is not iterable at <anonymous>:1:14, 至少在 Chrome 中
2021-03-12 10:30:28
获胜的 TS - 示例不正确,后者应返回“哺乳动物”,而不是 //“猫”、“狗”、“仓鼠”
2021-03-17 10:30:28
我记得它: for "in" for index然后对于“of”将是values每个索引/键/项目的。
2021-03-25 10:30:28
我记得它:for...inas Object.keys(),你猜怎么着?数组是对象,所以它也会返回它们的 indeces。:)
2021-03-28 10:30:28
很好,这对我来说将是王道:使用 for-ins 迭代项目我通常必须创建一个let thisItem = items[all];变量,这for...of有助于快捷方式!
2021-04-01 10:30:28

区别for..infor..of

for..infor..of被循环其在数据结构用于迭代构建体。它们之间的唯一区别是它们迭代的实体:

  1. for..in迭代对象的所有可枚举属性键
  2. for..of迭代可迭代对象可迭代对象的示例是数组、字符串和 NodeList。

例子:

let arr = ['el1', 'el2', 'el3'];

arr.addedProp = 'arrProp';

// elKey are the property keys
for (let elKey in arr) {
  console.log(elKey);
}

// elValue are the property values
for (let elValue of arr) {
  console.log(elValue)
}

在这个例子中,我们可以观察到for..in循环遍历对象的键,在这个例子中是一个数组对象。键是 0、1、2(对应于数组元素)和addedProp这是arr数组对象在 chrome devtools 中的外观:

在此处输入图片说明

你会看到我们的for..in循环只是简单地迭代这些键。


for..of我们的例子循环迭代的数据结构。此特定示例中的值为'el1', 'el2', 'el3'可迭代数据结构返回的for..of值取决于可迭代对象的类型。例如,数组将返回所有数组元素的值,而字符串将返回字符串的每个单独字符。

为什么不输出“arrProp”?
2021-03-10 10:30:28
@AlifRamdani 在这种情况下,特别是因为所讨论的对象是一个数组。这就是@Willem 的意思,“可迭代数据结构将使用的返回for..of值取决于可迭代对象的类型。” 在数组的情况下,这只是数字索引。
2021-03-30 10:30:28

For...in 循环

为...在循环,消除计数逻辑和退出条件在for循环的弱点得到改善。

例子:

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const index in digits) {
  console.log(digits[index]);
}

但是,您仍然必须处理使用索引访问数组值的问题,这很糟糕;它几乎使它比以前更加混乱。

此外,当您需要向数组(或其他对象)添加额外方法时,for...in 循环可能会给您带来大麻烦。因为 for...in 循环遍历所有可枚举的属性,这意味着如果您向数组的原型添加任何其他属性,那么这些属性也将出现在循环中。

Array.prototype.decimalfy = function() {
  for (let i = 0; i < this.length; i++) {
    this[i] = this[i].toFixed(2);
  }
};

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const index in digits) {
  console.log(digits[index]);
}

印刷:

0

1

2

3

4

5

6

7

8

9

function() { for (let i = 0; i < this.length; i++) { this[i] = this[i].toFixed(2); } }

这就是为什么在遍历数组时不鼓励使用 for...in 循环。

注意forEach 循环是 JavaScript 中另一种类型的 for 循环。但是,forEach()实际上是一种数组方法,因此只能与数组一起使用。也没有办法停止或中断 forEach 循环。如果您在循环中需要这种类型的行为,则必须使用基本的 for 循环。

For...of 循环

对...的循环用于遍历任何类型的数据是可迭代。

例子:

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  console.log(digit);
}

印刷:

0

1

2

3

4

5

6

7

8

9

这使得 for...of 循环成为所有 for 循环中最简洁的版本。

但是等等,还有更多!for...of 循环还有一些额外的好处,可以修复 for 和 for...in 循环的弱点。

您可以随时停止或中断 for...of 循环。

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  if (digit % 2 === 0) {
    continue;
  }
  console.log(digit);
}

印刷:

1

3

5

7

9

而且您不必担心向对象添加新属性。for...of 循环只会遍历对象中的值。

有点让人困惑的是,您为示例选择的数组值与数组索引值相对应...
2021-03-16 10:30:28
@Bergi 您能否澄清为什么您认为这不是它的作用,以及您实际上认为它改进了什么?
2021-03-20 10:30:28
for...in 循环通过消除计数逻辑和退出条件改进了 for 循环的弱点” - 不,这不是它的作用。一点也不。
2021-03-27 10:30:28
您的示例使用包含从 0 到 9 的数字的数组,这会使人们混淆,好像它们是索引,请将您的源数据更改为更具上下文的内容。
2021-03-29 10:30:28
它没有任何改进,它有自己的存在理由。它的作用与for (var index=0; index<arr.length; index++)循环完全不同(其中index计数器是一个整数,与您的示例不同)。
2021-04-03 10:30:28

这是一个有用的助记符,用于记住for...inLoop 和for...ofLoop之间的区别

“索引,对象”

for...in Loop=> 迭代数组中索引

for...of Loop=> 迭代对象的对象。