[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在ES5中便出現了。通常用來遍歷對象屬性。但也可用於數組遍歷,返回的值是數組的索引,由於,嚴格來講,數組也是一個對象,所對應的屬性是每一個值的索引。 for-in只遍歷對象自身的和繼承的可枚舉的屬性(摘自 阮一峯ECMAScript 6 入門-對象擴展一章)。
如[4]、[5]、[6]所示,爲數組添加可遍歷屬性 (所對應描述器descriptor的enumerable屬性爲true) ,在[7]中用for-in遍歷均可遍歷出來。數組
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的實例,並非數組實例。