1. 程式人生 > >(for in)遍歷鍵名和 (for of)遍歷鍵值,這種說法嚴謹嗎?

(for in)遍歷鍵名和 (for of)遍歷鍵值,這種說法嚴謹嗎?

[1] const arr = [7, 8, 9];
const obj = {
  a: 4,
  b: 5,
  c: 6
};
[2] for (let v in arr){
 console.log(v);
}
// 0, 1, 2
[3 ]for (let v in obj){
 console.log(v);
}
// a, b, c
[4] arr.child = 'child';
[5] arr.__proto__.getChild = function () {
    return this.child;
     };
[6] Array.prototype.parent = 'parent';
[7] for (let v in arr){
        console.log(v);
     }
//  0, 1, 2, child, getChild, parent
[8]for (let v of arr){
       console.log(v);
    }
// 7, 8, 9
[9] for (let v of arr.values()){
       console.log(v);
    }
// 7, 8, 9
[10] for (let v of obj){
       console.log(v);
    }
// 報錯 
[11] typeof arr.keys(); // 'object'
arr.keys() instanceof Array; // false
arr.keys() instanceof Object; // true

for in

for in在ES5中便出現了。一般用來遍歷物件屬性。但也可用於陣列遍歷,返回的值是陣列的索引,因為,嚴格來說,陣列也是一個物件,所對應的屬性是每個值的索引。 for-in只遍歷物件自身的和繼承的可列舉的屬性(摘自 阮一峰ECMAScript 6 入門-物件擴充套件一章)。如[4]、[5]、[6]所示,為陣列新增可遍歷屬性 (所對應描述器descriptor的enumerable屬性為true) ,在[7]中用for-in遍歷都可遍歷出來。

for of

for of為ES6新增遍歷方法。其可遍歷所有具有 iterator 介面的資料結構。for...of迴圈內部呼叫的是資料結構的Symbol.iterator方法(generator函式)。(摘自 阮一峰ECMAScript 6 入門--Iterator 和 for...of 迴圈一章)

。Symbol.iterator方法返回的是一個遍歷器,當用for-of去遍歷的時候, 自動呼叫裡面的next方法。如[8], [9]所示,陣列原生具備iterator介面(即預設部署了Symbol.iterator屬性),for...of迴圈本質上就是呼叫這個介面產生的 遍歷器。再看?例子 (摘自 阮一峰ECMAScript 6 入門--Iterator 和 for...of 迴圈一章),物件obj預設呼叫的遍歷器生成器是obj.values即obj[Symbol.iterator] 。

const colorArr = ['red', 'green', 'blue'];
for(let v of colorArr) {
  console.log(v); 
}
// red green blue
const colorObj = {};
colorObj[Symbol.iterator] = colorArr[Symbol.iterator].bind(colorArr);

for(let v of colorObj) {
  console.log(v); 
}
// red green blue

總結

所以說,(for in)遍歷鍵名和 (for of)遍歷鍵值,這種說法並不嚴謹。for in確實是遍歷屬性,而且更是遍歷物件自身的和繼承的可列舉的屬性。但是,for of遍歷鍵值這種說法便不嚴謹了,比如說我們一開始在[1]中宣告的物件obj,鍵名為a,b, c; 鍵值為4,5,6;

  • 按照(for of)遍歷鍵值這種說法,用for of遍歷obj應該返回鍵值4,5,6。可是如[10]所示,程式執行報錯了。因為物件預設是沒有iterator介面的,我們不可以直接遍歷,當我們需要遍歷物件的屬性時,可以呼叫Object.keys()返回一個數組,用來遍歷所有的鍵名。當我們需要遍歷物件的屬性值時,應該呼叫obj.values()返回一個數組,用來遍歷所有的鍵值。並不是說for-of遍歷鍵值,for-of具體遍歷並返回的是什麼,是視of後面返回的陣列對應是什麼。就obj這個物件來說,我們可以遍歷obj的鍵值(Object.values(obj)),也可以遍歷obj的鍵名(Object.keys(obj)),更可以遍歷物件的obj的鍵值對(Object.entires(obj))。
  • 同樣。for-of遍歷陣列,陣列是預設具有iterator介面的,即arr.values(),具體遍歷並返回的是什麼,是視of後面返回的遍歷器物件是什麼。arr的鍵值(arr.values()),也可以遍歷陣列arr的鍵名(arr.keys()),更可以遍歷陣列的arr的鍵值對(arr.entires())。
  • 遍歷器物件是一個物件,不是陣列。如[11]所示,arr.keys() 是物件Object的例項,並不是陣列例項。