我知道什么是a。在循环中(它在键上迭代),但我听说for…的第一次(它遍历值)。

我对……感到困惑。的循环。

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

我理解为……Of迭代属性值。那为什么它记录的不是"3" "5" "7" "hello"而是"3" "5" "7"

不像……循环中,遍历每个键("0","1","2","foo"),也遍历foo键,for…Of不会遍历foo属性的值,即“hello”。为什么会这样?

在此我为……的循环。它应该日志“3”,“5”,“7”,“你好”,但日志“3”,“5”,“7”。为什么?

例子链接


For in循环遍历对象的可枚举属性名。

for of (ES6新增功能)使用特定于对象的迭代器并遍历由该迭代器生成的值。

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


我在迭代器和生成器中找到了完整的答案(虽然它适用于TypeScript,但也适用于JavaScript)

Both for..of and for..in statements iterate over lists; the values iterated on are different though, for..in returns a list of keys on the object being iterated, whereas for..of returns 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..of on the other hand, is mainly interested in values of iterable objects. Built-in objects like Map and Set implement Symbol.iterator property 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-in语句以任意顺序遍历对象的可枚举属性。

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

你可以把它理解为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"]

为…在循环

为…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循环可能会给您带来大麻烦。因为……在循环中,循环遍历所有可枚举的属性,这意味着如果您向数组的原型添加任何额外的属性,那么这些属性也将出现在循环中。

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 函数(){ for(设I = 0;I < this.length;我+ +){ this[i] = this[i].toFixed(2); } }

这就是为什么……当循环遍历数组时,不鼓励使用In循环。

注意:forEach循环是JavaScript中的另一种for循环。 然而,forEach()实际上是一个数组方法,因此只能使用它 仅用于数组。也没有办法停止或打破一个 forEach循环。如果你的循环中需要这种类型的行为,你会 必须使用一个基本的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

这使得……Of loop是所有for循环中最简洁的版本。

但是等等,还有更多!为…Of循环还有一些额外的优点,可以修复for和for…在循环。

你可以stop或break for…的循环。

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

您不必担心向对象添加新属性。为…Of循环将只循环遍历对象中的值。


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

为…语句对iterable对象定义的要迭代的数据进行迭代。

例子:

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
}

像前面一样,你可以跳过添加hasOwnProperty在…的循环。


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

正常情况下,for in在迭代器上迭代,in response为我们提供了按插入顺序排列的键,如下例所示。

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

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

现在如果我们对for of进行同样的操作,那么作为响应,它提供给我们的是值而不是键。如

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

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

因此,观察这两个迭代器,我们可以很容易地区分它们之间的区别。

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

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

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是不可迭代的

现在为了遍历,我们需要定义一个ES6 Symbol。迭代器如

  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

这就是For in和For of的区别。希望能消除这种差异。


每个人都解释了为什么会出现这个问题,但是仍然很容易忘记它,然后挠头为什么会得到错误的结果。尤其是当你处理大量数据时,乍一看结果似乎还不错。

使用对象。你确保去所有属性的条目:

var arr = [3, 5, 7];
arr.foo = "hello";

for ( var [key, val] of Object.entries( arr ) ) {
   console.log( val );
}

/* Result:

3
5
7
hello

*/

for. in和for. of的区别:

for..in和for..of都是循环结构,用于遍历数据结构。它们之间唯一的区别是实体 它们迭代:

For ..in迭代对象的所有可枚举属性键 For ..of迭代可迭代对象的值。可迭代对象的例子有数组、字符串和nodelist。

例子:

Let arr = ['el1', 'el2', 'el3']; 加勒比海盗。adddedprop = 'arrProp'; // elKey是属性键 for(让elKey在arr中){ console.log (elKey); } // elValue是属性值 for (let elValue of arr) { console.log (elValue) }

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

你可以看到,我们的for..in循环只是简单地遍历这些键。


示例中的for..of循环遍历数据结构的值。这个例子中的值是'el1', 'el2', 'el3'。可迭代数据结构使用for..of返回的值取决于可迭代对象的类型。例如,数组将返回所有数组元素的值,而字符串则返回字符串中的每个字符。


A看到了很多好的答案,但我决定把我的5美分只是为了有一个好的例子:

For in循环

遍历所有可枚举的道具

let nodes = document.documentElement.childNodes; 对于(var键在节点中){ Console.log (key); }

For循环

遍历所有可迭代值

let nodes = document.documentElement.childNodes; 对于(var节点中的节点){ console.log(node.toString()); }


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

解构……In已弃用。用于……相反。

因此,如果我们想在循环中使用解构,为了获取每个数组元素的索引和值,我们应该使用for…使用Array方法条目():

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

当我第一次开始学习for in和of循环时,我也对我的输出感到困惑,但通过一些研究和理解,你可以像下面这样思考单个循环: 的

为…在循环中返回单个属性的索引,对属性的值没有影响,它循环并返回关于属性的信息,而不是关于属性的值。 如

Let profile = { 名字叫拿弗他利。 年龄:24岁 favCar:“野马”, 最喜欢的饮料:百利酒 }

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

现在让我们用for…在下面的循环中

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

现在输出的原因是,我们的配置文件对象中有四(4)个属性,我们都知道索引从0开始…N,我们得到了属性的下标0,1,2,3因为我们使用的是for. in循环。

for...of loop* can return either the property, value or both, 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 keys or properties of an object. Object.values(object-name-goes-here) >>> Returns the values of an object. Object.entries(object-name-goes-here) >>> Returns both the keys and values of an object.


下面是它们的用法示例,请注意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}`)
               }

当使用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}`)
                   }

对不清楚的部分提出意见。


这里有一个有用的助记符来记住for…in Loop和for…的循环。

索引的对象

为…in Loop =>迭代数组中的索引。

为…of Loop =>遍历对象的对象。


为…Of循环只对可迭代对象有效。在JavaScript中,可迭代对象是可以循环的对象。

String、Array、TypedArray、Map和Set都是内置的可迭代对象,因为它们的每个原型对象都实现了@@iterator方法。因此,对于…Of循环作用于上述的对象类型。

Object在JavaScript中默认是不可迭代的。因此,对于…Of循环对对象无效。

简单地说,对于……Of适用于字符串和数组,但不适用于对象。

为…In适用于那些可枚举标志设置为true的属性。

通过简单赋值或属性初始化器创建的属性的可枚举标志默认为true。 通过Object.defineProperty创建的属性的可枚举标志默认为false。

这里有一个更详细的例子:https://dev.to/swastikyadav/difference-between-forof-and-forin-loop-in-javascript-j2o


简单的回答:为了……在键上循环,而for…对值的循环。

for (let x in ['a', 'b', 'c', 'd'] {
    console.log(x); 
}

// Output
0
1
2
3


for (let x of ['a', 'b', 'c', 'd'] {
    console.log(x); 
}

// Output
a
b
c
d

//for in,迭代对象中的键和数组中的索引

 let obj={a:1, b:2}
    
    for( const key in obj)
      console.log(obj[key]); //would print 1 and 2
      console.log(key);      //would print a and b

 let arr = [10, 11, 12, 13];

  for (const item in arr) 
    console.log(item);   //would print 0 1 2 3

//for of,迭代数组或任何可迭代对象中的值

let arr = [10, 11, 12, 13];

for (const item of arr )
  console.log(item);  //would print 10  11  12  13

For of用于遍历可迭代对象,For in用于遍历对象属性

这里有一个要记住的小技巧:

For of不是针对对象的(而是针对可迭代对象的)

For in不是针对可迭代对象的,而是针对对象的

另一个技巧:

For in返回对象索引(键),而For of返回值


简单来说,forIN遍历数组(索引)/对象(键)中的key, 而forOF则遍历数组(value)的值。