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

Javascript (for…in)和(for…of)语句之间有什么区别?,javascript,arrays,for-loop,object,Javascript,Arrays,For Loop,Object,我知道什么是。。。在循环中(它在键上迭代),但我听说了关于。。。第一次使用(它对值进行迭代) 我对。。。属于循环 var-arr=[3,5,7]; arr.foo=“你好”; 用于(arr中的var i){ console.log(i);//日志“0”、“1”、“2”、“foo” } 用于(arr的var i){ console.log(i);//日志“3”、“5”、“7” //它不记录“3”,“5”,“7”,“你好” } 我理解,对于。。。of迭代属性值。那么为什么它不记录“3”、“5”、“

我知道什么是
。。。在
循环中(它在键上迭代),但我听说了关于。。。第一次使用(它对值进行迭代)

我对。。。属于循环

var-arr=[3,5,7];
arr.foo=“你好”;
用于(arr中的var i){
console.log(i);//日志“0”、“1”、“2”、“foo”
}
用于(arr的var i){
console.log(i);//日志“3”、“5”、“7”
//它不记录“3”,“5”,“7”,“你好”
}
我理解,
对于。。。of
迭代属性值。那么为什么它不记录
“3”、“5”、“7”、“hello”而不是
“3”、“5”、“7”

不同于。。。在
循环中,它迭代每个键(
“0”、“1”、“2”、“foo”
),也迭代
foo
键,
用于。。。of
不会迭代
foo
属性的值,即
“hello”
。为什么会这样

我在这里为。。。属于循环。它应该记录
“3”、“5”、“7”、“hello”
,但它记录
“3”、“5”、“7”
。为什么?

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

(在ES6中新增)确实使用了一个and循环来覆盖由它生成的值


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

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

for..of
for..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
对任何对象进行操作;它服务于 作为检查此对象属性的一种方法<代码>用于另一个上的..of 另一方面,主要对可编辑对象的值感兴趣。内置 对象,如
Map
Set
实现
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 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"]
循环中的 该循环通过消除计数逻辑和退出条件,改进了for循环的缺点

例如:

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

for (const index in digits) {
  console.log(digits[index]);
}
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  console.log(digit);
}
但是,您仍然需要处理使用索引访问数组值的问题,这很糟糕;这几乎使它比以前更令人困惑

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

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

一,

二,

三,

四,

五,

六,

七,

八,

九,

这使得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);
}
印刷品:

一,

三,

五,

七,

九,


您不必担心向对象添加新属性。for…of循环将仅循环对象中的值。

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

for…of
语句迭代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在迭代器上进行迭代,并作为响应向我们提供按插入顺序排列的键,如下面的示例所示

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

   // result: 0, 1, 2, 3, 4
现在,如果我们对of尝试相同的,那么作为响应,它会为我们提供值,而不是键。e、 g

  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);
 } 
房间不适宜居住

现在,对于迭代,我们需要定义一个ES6符号

  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

这是in的与of的之间的差异。希望它能消除这种差异

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

使用
Object.entries
可确保浏览所有属性:

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 (const [idx, el] of arr.entries()) {
    console.log( idx + ': ' + el );
}
let arr = ["Apple", "Orange", "Pear"];

for (let i = 0; i < arr.length; i++) { alert( arr[i] ); } But for arrays there is another form of loop, for..of:

let fruits = ["Apple", "Orange", "Plum"];

// iterates over array elements for (let fruit of fruits) { alert( fruit ); } The for..of doesn’t give access to the number of the current element, just its value, but in most cases that’s enough. And it’s shorter.
let arr = ["Apple", "Orange", "Pear"];

for (let key in arr) { alert( arr[key] ); // Apple, Orange, Pear } But that’s actually a bad idea. There are potential problems with it:
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
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}`)
               }
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}`)
                   }