JavaScript中的for语句和for语句之间有什么区别?

2020/09/27 03:01 · javascript ·  · 0评论

我知道什么是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 is does not log "3", "5", "7", "hello"
}

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

总而言之:

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

范例连结

for in 遍历对象的可枚举属性名称。

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

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

我在以下位置找到了完整的答案:https : //www.typescriptlang.org/docs/handbook/iterators-and-generators.html(尽管它是针对类型脚本的,但对于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另一方面,主要关注可迭代对象的值。内置对象(例如Map和Set implement 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..infor..of

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

  1. for..in遍历对象的所有可枚举的属性键
  2. for..of迭代一个可迭代对象可迭代对象的示例是数组,字符串和NodeLists。

例:

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这是arrchrome devtools中数组对象的外观:

在此处输入图片说明

您会看到我们的for..in循环只不过是迭代这些值而已。


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

对于...在循环中

为...在循环,消除计数逻辑和退出条件在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循环。

对于... 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循环只会循环遍历对象中的值。

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

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

例:

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
}

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

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 numbers = [1,2,3,4,5];
   for(let number in number) {
     console.log(number);
   }

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

现在,如果我们对for进行尝试,那么作为响应,它将为我们提供值而不是键。例如

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

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

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

注: - 对于只能与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 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

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

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

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

资源

因此,如果我们想在循环中使用解构,以获取每个数组元素的索引,则应将循环与Array方法一起使用for...ofentries()

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

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

“索引,对象”

for...in Loop=>遍历数组中索引

for...of Loop=>遍历对象的对象。

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

使用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

*/

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

对于循环

遍历所有可枚举的道具

let nodes = document.documentElement.childNodes;

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

对于循环

迭代所有可迭代的值

let nodes = document.documentElement.childNodes;

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

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

  1. for ... in 循环返回单个属性索引,并且属性的值没有影响,它循环并返回有关属性而不是 value的信息例如

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

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

现在让我们下面使用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

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

  1. for ... of循环*可以返回propertyvalue 两者都返回,让我们看看如何。在javaScript中,我们无法像在数组上那样正常地遍历对象,因此,可以使用一些元素来访问对象中的任一个选择。

    • Object.keysobject-name-goes-here)>>>返回对象属性

    • Object.valuesobject-name-goes-here)>>>返回对象

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

以下是其用法示例,请注意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

for-in循环用于以任意顺序遍历集合的可枚举属性集合是容器类型的对象,其项目可以使用索引或键。

var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];
var myString = "123";

console.log( myObject[ 'a' ], myArray[ 1 ], myString[ 2 ] );

for-in循环一次提取一个集合的所有可枚举的属性(),然后一次遍历它。可枚举属性是可以for-in循环出现的集合的属性

默认情况下,数组和对象的所有属性都for-in循环出现但是,我们可以使用Object.defineProperty方法来手动配置集合的属性。

var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];

Object.defineProperty( myObject, 'd', { value: 4, enumerable: false } );
Object.defineProperty( myArray, 3, { value: 4, enumerable: false } );

for( var i in myObject ){ console.log( 'myObject:i =>', i ); }
for( var i in myArray ){ console.log( 'myArray:i  =>', i ); }

在上面的例子中,属性dmyObject和指数3myArray未出现在for-in,因为它们与配置循环enumerable: false

for-in循环几乎没有问题在使用Arrays的情况下,for-in循环也将考虑methods使用myArray.someMethod = f语法将其添加到数组中,但是myArray.length仍然保留4

for-of

for-of循环迭代集合的值是一种误解for-of循环遍历Iterable对象。一个可迭代对象是Symbol.iterator在其原型之一中直接具有名称的方法的对象

Symbol.iterator方法应返回Iterator迭代器是具有next方法的对象当调用return valuedoneproperties 时,此方法

当我们使用循环迭代一个可迭代对象时for-ofSymbol.iterator一旦获得一个迭代器对象该方法将被调用对于每一个迭代for-of循环,next该迭代器对象的方法将被调用,直到done在返回next()调用返回false。for-of如果调用value返回了该属性,则循环在每次迭代中收到的值next()

var myObject = { a: 1, b: 2, c: 3, d: 4 };

// make `myObject` iterable by adding `Symbol.iterator` function directlty on it
myObject[ Symbol.iterator ] = function(){
  console.log( `LOG: called 'Symbol.iterator' method` );
  var _myObject = this; // `this` points to `myObject`
  
  // return an iterator object
  return {
    keys: Object.keys( _myObject ), 
    current: 0,
    next: function() {
      console.log( `LOG: called 'next' method: index ${ this.current }` );
      
      if( this.current === this.keys.length ){
        return { done: true, value: null }; // Here, `value` is ignored by `for-of` loop
      } else {
        return { done: false, value: _myObject[ this.keys[ this.current++ ] ] };
      }
    }
  };
}

// use `for-of` loop on `myObject` iterable
for( let value of myObject ) {
  console.log( 'myObject: value => ', value );
}

for-of回路处于ES6新等都是可迭代IterablesArray构造类型都有Symbol.iterator它的原型方法。Object构造可悲的是没有它,但是Object.keys()Object.values()Object.entries()方法返回一个可迭代(你可以用console.dir(obj)检查原型方法)。for-of循环的好处是可以使任何对象都是可迭代的,即使您的自定义DogAnimal类也是如此。

使对象可迭代的简单方法是实现ES6 Generator,而不是自定义迭代器实现。

不同于for-infor-of循环可以等待异步任务在每次迭代中完成。这是通过awaitfor语句文档之后使用关键字来实现的

for-of循环的另一个好处是它具有Unicode支持。根据ES6规范,字符串以UTF-16编码存储。因此,每个字符都可以采用16-bit32-bit传统上,字符串以UCS-2编码存储,该编码支持16 bits可存储在其中的字符

因此,String.length返回16-bit字符串中像表情符号字符这样的现代字符需要32位。因此,此字符将返回length2. for-in循环遍历16-bit块并返回错误的index但是,for-of循环根据UTF-16规范遍历单个字符。

var emoji = "😊🤣";

console.log( 'emoji.length', emoji.length );

for( var index in emoji ){ console.log( 'for-in: emoji.character', emoji[index] ); }
for( var character of emoji ){ console.log( 'for-of: emoji.character', character ); }

我发现来自https://javascript.info/array的以下解释非常有帮助:

循环数组项的最古老方法之一是for循环索引:

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.

从技术上讲,因为数组是对象,所以也可以将..in用于:

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:

in。的循环遍历所有属性,而不仅仅是数字属性。

浏览器和其他环境中有所谓的“类似数组的”对象,看起来像数组。也就是说,它们具有长度和索引属性,但它们也可能具有其他通常不需要的非数字属性和方法。for..in循环将列出它们。因此,如果我们需要处理类似数组的对象,那么这些“额外”属性可能会成为问题。

for..in循环针对通用对象而非数组进行了优化,因此速度要慢10-100倍。当然,它仍然非常快。加速可能仅在瓶颈方面起作用。但是我们仍然应该意识到其中的区别。

通常,我们不应该将for..in用于数组。

本文地址:http://javascript.askforanswer.com/javascriptzhongdeforyujuheforyujuzhijianyoushenmequbie.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!