JavaScript 中的 ( for... in ) 和 ( for... of ) 语句有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29285897/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:05:59  来源:igfitidea点击:

What is the difference between ( for... in ) and ( for... of ) statements in JavaScript?

javascriptarraysobject

提问by Mukund Kumar

I know what is for... inloop (it iterates over key), but heard the first time about for... of(it iterates over value).

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

I am confused with for... ofloop. I didn't get adject. This is the code below :

我对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 is does not log "3", "5", "7", "hello"
}

What I got is, for... ofiterates over property values. Then why it doesn't log (return) "3", "5", "7", "hello"instead of "3", "5", "7"? but for... inloop iterates over each key ("0", "1", "2", "foo"). Here for... inloop also iterates over fookey. But for... ofdoes not iterate over the value of fooproperty i.e "hello". Why it is like that?

我得到的是,for... of迭代属性值。那么为什么它不记录(返回)"3", "5", "7", "hello"而不是记录"3", "5", "7"?但for... in循环遍历每个键 ( "0", "1", "2", "foo")。这里的for... in循环也遍历foo键。但for... of不会迭代foo属性 ie的值"hello"。为什么会这样?

Long story in short:

长话短说:

Here I console for... ofloop. It should log "3", "5", "7","hello"but here it logs "3", "5", "7". Why ?

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

Example Link

示例链接

采纳答案by Bergi

for inloops over enumerable property names of an object.

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

for of(new in ES6) does use an object-specific iteratorand loops over the values generated by that.

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

In your example, the array iteratordoes yield all the values in the array (ignoring non-index properties).

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

回答by Alireza Fattahi

I find a complete answer at : https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html(Although it is for type script, this is same for javascript too)

我在以下位置找到了完整的答案:https: //www.typescriptlang.org/docs/handbook/iterators-and-generators.html(虽然它是针对类型脚本的,但对于 javascript 也是如此)

Both for..ofand for..instatements iterate over lists; the values iterated on are different though, for..inreturns a list of keys on the object being iterated, whereas for..ofreturns a list of values of the numeric properties of the object being iterated.

Here is an example that demonstrates this distinction:

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"
}

Another distinction is that for..in operates on any object; it serves as a way to inspect properties on this object. for..ofon the other hand, is mainly interested in values of iterable objects. Built-in objects like Map and Set implement Symbol.iteratorproperty allowing access to stored values.

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..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另一方面,主要对可迭代对象的值感兴趣。内置对象,如 Map 和 Setimplement 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"
}

回答by Elar

For...in loop

For...in 循环

The for...inloop improves upon the weaknesses of the for loop by eliminating the counting logic and exit condition.

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

Example:

例子:

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

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

But, you still have to deal with the issue of using an index to access the values of the array, and that stinks; it almost makes it more confusing than before.

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

Also, the for...in loop can get you into big trouble when you need to add an extra method to an array (or another object). Because for...in loops loop over all enumerable properties, this means if you add any additional properties to the array's prototype, then those properties will also appear in the loop.

此外,当您需要向数组(或其他对象)添加额外方法时,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]);
}

Prints:

印刷:

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); ?} }

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); ?} }

This is why for...in loops are discouraged when looping over arrays.

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

NOTE: The forEach loopis another type of for loop in JavaScript. However, forEach()is actually an array method, so it can only be used exclusively with arrays. There is also no way to stop or break a forEach loop. If you need that type of behavior in your loop, you'll have to use a basic for loop.

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

For...of loop

For...of 循环

The for...ofloop is used to loop over any type of data that is iterable.

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

Example:

例子:

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

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

Prints:

印刷:

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

This makes the for...of loop the most concise version of all the for loops.

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

But wait, there's more! The for...of loop also has some additional benefits that fix the weaknesses of the for and for...in loops.

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

You can stop or break a for...of loop at anytime.

您可以随时停止或中断 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);
}

Prints:

印刷:

1

3

5

7

9

1

3

5

7

9

And you don't have to worry about adding new properties to objects. The for...of loop will only loop over the values in the object.

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

回答by Willem van der Veen

Difference for..inand for..of:

区别for..infor..of

Both for..inand for..ofare looping constructs which are used to iterate over data structures. The only difference is over what they iterate:

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

  1. for..initerates over all enumerable property keysof an object
  2. for..ofiterates over the valuesof an iterable object. Examples of iterable objects are arrays, strings, and NodeLists.
  1. for..in迭代对象的所有可枚举属性键
  2. for..of迭代可迭代对象的。可迭代对象的示例是数组、字符串和 NodeList。

Example:

例子:

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)
}

In this example we can observe that the for..inloop iterates over the keys of the object, which is an array object in this example. The keys are 0, 1, 2 which correspond to the array elements we added and addedProp. This is how the arrarray object looks in chrome devtools:

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

enter image description here

在此处输入图片说明

You see that our for..inloop does nothing more than simply iterating over these values.

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



The for..ofloop in our example iterates over the valuesof a data structure. The values in this specific example are 'el1', 'el2', 'el3'. The values which an iterable data structure will return using for..ofis dependent on the type of iterable object. For example an array will return the values of all the array elements whereas a string returns every individual character of the string.

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

回答by Ramandeep Sohi

The for...instatement iterates over the enumerable properties of an object, in an arbitrary order. Enumerable properties are those properties whose internal [[Enumerable]] flag is set to true, hence if there is any enumerable property in the prototype chain, the for...inloop will iterate on those as well.

for...in语句以任意顺序迭代对象的可枚举属性。可枚举属性是那些内部 [[Enumerable]] 标志设置为 true 的属性,因此如果原型链中有任何可枚举属性,for...in循环也会迭代这些属性。

The for...ofstatement iterates over data that iterable object defines to be iterated over.

for...of语句迭代可迭代对象定义要迭代的数据。

Example:

例子:

Object.prototype.objCustom = function() {}; 
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];

for (let i in iterable) {
  console.log(i); // logs: 0, 1, 2, "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs: 0, 1, 2,
  }
}

for (let i of iterable) {
  console.log(i); // logs: 3, 5, 7
}

Like earlier, you can skip adding hasOwnPropertyin for...ofloops.

与早期的,你可以跳过添加hasOwnPropertyfor...of循环。

回答by Devdutta Natu

The for-in statement iterates over the enumerable properties of an object, in arbitrary order.

for-in 语句以任意顺序迭代对象的可枚举属性。

The loop will iterate over all enumerable properties of the object itself and those the object inherits from its constructor's prototype

循环将遍历对象本身的所有可枚举属性以及对象从其构造函数的原型继承的属性

You can think of it as "for in" basically iterates and list out all the keys.

您可以将其视为“for in”基本上迭代并列出所有键。

var str = 'abc';
var arrForOf = [];
var arrForIn = [];

for(value of str){
  arrForOf.push(value);
}

for(value in str){
  arrForIn.push(value);
}

console.log(arrForOf); 
// ["a", "b", "c"]
console.log(arrForIn); 
// ["0", "1", "2", "formatUnicorn", "truncate", "splitOnLast", "contains"]

回答by Amit Mundra

There are some already defined data types which allows us to iterate over them easily e.g Array, Map, String Objects

有一些已经定义的数据类型允许我们轻松地迭代它们,例如数组、映射、字符串对象

Normal for initerates over the iterator and in response provides us with the keys that are in the order of insertion as shown in below example.

正常for in迭代迭代器并作为响应为我们提供按插入顺序排列的键,如下例所示。

  const numbers = [1,2,3,4,5];
   for(let number in number) {
     console.log(number);
   }

   // result: 0, 1, 2, 3, 4

Now if we try same with for of, then in response it provides us with the values not the keys. e.g

现在,如果我们尝试使用for of,那么作为响应,它为我们提供了值而不是键。例如

  const numbers = [1,2,3,4,5];
   for(let numbers of numbers) {
    console.log(number);
  }

  // result: 1, 2, 3, 4, 5

So looking at both of the iterators we can easily differentiate the difference between both of them.

因此,查看这两个迭代器,我们可以轻松区分它们之间的差异。

Note:- For ofonly works with the Symbol.iterator

注意:- For of仅适用于 Symbol.iterator

So if we try to iterate over normal object, then it will give us an error e.g-

所以如果我们尝试迭代普通对象,那么它会给我们一个错误,例如-

const Room = {
   area: 1000,
   height: 7,
   floor: 2
 }

for(let prop in Room) {
 console.log(prop);
 } 

// Result area, height, floor

for(let prop of Room) {
  console.log(prop);
 } 

Room is not iterable

房间不可迭代

Now for iterating over we need to define an ES6 Symbol.iterator e.g

现在为了迭代我们需要定义一个 ES6 Symbol.iterator 例如

  const Room= {
    area: 1000, height: 7, floor: 2,
   [Symbol.iterator]: function* (){
    yield this.area;
    yield this.height;
    yield this.floors;
  }
}


for(let prop of Room) {
  console.log(prop);
 } 

//Result 1000, 7, 2

This is the difference between For inand For of. Hope that it might clear the difference.

这是For inFor of之间的区别。希望它可以消除差异。

回答by simhumileco

Another differencebetween the two loops, which nobody has mentioned before:

两个循环之间的另一个区别,之前没有人提到过:

Destructuring for...inis deprecated. Use for...ofinstead.

拆解for...in已被弃用。使用for...of来代替。

Source

来源

So if we want to use destructuringin a loop, for get both indexand valueof each arrayelement, we should to use the for...ofloop with the Arraymethod entries():

所以如果我们想在循环中使用解构,为了获取每个数组元素的索引,我们应该使用带有Array方法的循环:for...ofentries()

for (const [idx, el] of arr.entries()) {
    console.log( idx + ': ' + el );
}

回答by WebBrother

A see a lot of good answers, but I decide to put my 5 cents just to have good example:

看到很多好的答案,但我决定把我的 5 美分放在一个很好的例子中:

For in loop

for 循环

iterates over all enumerable props

迭代所有可枚举的道具

let nodes = document.documentElement.childNodes;

for (var key in nodes) {
  console.log( key );
}

For of loop

for 循环

iterates over all iterable values

迭代所有可迭代值

let nodes = document.documentElement.childNodes;

for (var node of nodes) {
  console.log( node.toString() );
}

回答by Naphtali Duniya

When I first started out learning the for inand of loop, I was confused with my output too, but with a couple of research and understanding you can think of the individual loop like the following : The

当我第一次开始学习for inof 循环时,我也对我的输出感到困惑,但是通过一些研究和理解,您可以将单个循环视为如下:

  1. for...inloopreturns the indexesof the individual property and has no effectof impact on the property's value, it loops and returns information on the propertyand not the value. E.g
  1. for...in循环返回单个属性的索引并且对属性的 value没有影响,它循环并返回关于属性而不是value 的信息。例如

let profile = { name : "Naphtali", age : 24, favCar : "Mustang", favDrink : "Baileys" }

let profile = { name : "Naphtali", age : 24, favCar : "Mustang", favDrink : "Baileys" }

The above code is just creating an objectcalled profile, we'll use it for both our examples, so, don't be confused when you see the profile objecton an example, just know it was created.

上面的代码只是创建了一个名为profile对象,我们将在我们两个示例中使用它,因此,当您在示例中看到profile 对象时不要感到困惑,只要知道它是创建的。

So now let us use the for...in loopbelow

所以现在让我们使用下面的for...in 循环

for(let myIndex in profile){
    console.log(`The index of my object property is ${myIndex}`)
}
 // Outputs : 
        The index of my object property is 0
        The index of my object property is 1
        The index of my object property is 2
        The index of my object property is 3

Now Reason for the output being that we have Four(4)properties in our profileobject and indexing as we all know starts from 0...n, so, we get the index of properties 0,1,2,3since we are working with the for..inloop.

现在输出的原因是我们的配置文件对象中有四(4)个属性,并且众所周知,索引从0...n开始,因此,我们得到属性0,1,2,3的索引,因为我们是使用for..in循环。

  1. for...of loop*can return either the property, valueorboth, Let's take a look at how. In javaScript, we can't loop through objects normally as we would on arrays, so, there are a few elements we can use to access either of our choices from an object.

    • Object.keys(object-name-goes-here) >>> Returns the keysor propertiesof an object.

    • Object.values(object-name-goes-here) >>> Returns the valuesof an object.

    • Object.entries(object-name-goes-here) >>> Returns boththe keysand valuesof an object.
  1. for...of loop*可以返回propertyvalueboth,让我们看看如何。在 javaScript 中,我们不能像在数组上那样正常循环遍历对象,因此,我们可以使用一些元素来访问对象中的任一选择。

    • Object.keys( object-name-goes-here) >>> 返回对象的属性

    • Object.values( object-name-goes-here) >>> 返回对象的

    • Object.entries对象名称GOES-这里)>>>返回两者的对象。


Below are examples of their usage, pay attention to Object.entries():

下面是它们的用法示例,注意 Object.entries()

Step One: Convert the object to get either its key, value, or both.
Step Two: loop through.


// Getting the keys/property

   Step One: let myKeys = ***Object.keys(profile)***
   Step Two: for(let keys of myKeys){
             console.log(`The key of my object property is ${keys}`)
           }

// Getting the values of the property

    Step One: let myValues = ***Object.values(profile)***
    Step Two : for(let values of myValues){
                 console.log(`The value of my object property is ${values}`)
               }

When using Object.entries()have it that you are calling two entries on the object, i.ethe keys and values. You can call both by either of the entry. Example Below.

使用Object.entries()时,您要调用对象上的两个条目,键和值。您可以通过任一条目调用两者。示例如下。

Step One: Convert the object to entries, using ***Object.entries(object-name)***
Step Two: **Destructure** the ***entries object which carries the keys and values*** 
like so **[keys, values]**, by so doing, you have access to either or both content.


    // Getting the keys/property

       Step One: let myKeysEntry = ***Object.entries(profile)***
       Step Two: for(let [keys, values] of myKeysEntry){
                 console.log(`The key of my object property is ${keys}`)
               }

    // Getting the values of the property

        Step One: let myValuesEntry = ***Object.entries(profile)***
        Step Two : for(let [keys, values] of myValuesEntry){
                     console.log(`The value of my object property is ${values}`)
                   }

    // Getting both keys and values

        Step One: let myBothEntry = ***Object.entries(profile)***
        Step Two : for(let [keys, values] of myBothEntry){
                     console.log(`The keys of my object is ${keys} and its value 
is ${values}`)
                   }

Make comments on unclear parts section(s).

对不清楚的部分部分发表评论。