[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的实例,并非数组实例。