你不知道的JS系列 ( 39 ) - 对象遍历
for 循环可以遍历数组
var myArray = [1,2,3]; for(var i=0; i<myArray.length; i++) { console.log(myArray[i]) } // 1 2 3
ES5 增加了数组的辅助迭代器,包括 forEach(...)、every(...)、some(...)
forEach(...) 会遍历数组中的所有值并忽略回调函数的返回值
every(...) 会一直运行直到回调返回 false
some(...) 会一只运行直到回到函数返回 true
for..in 循环可以用来遍历对象的可枚举属性列表(包括原型链)。使用 for..in 遍历对象是无法直接获取属性值的,因为实际上遍历的是对象中的所有可枚举属性,需要手动获取属性值
遍历数组下标时采用的是数字顺序,但是遍历对象属性时的顺序是不确定的,因此,在不同环境中需要保证一致性时,一定不要相信任何观察到的顺序
那么如何遍历值而不是下标和属性呢,使用 ES6 增加的 for..of 循环语法
var myArray = [1,2,3]; for(var v of myArray){ console.log(v) } // 1 2 3
for..of 循环首先会向被访问对象请求一个迭代器对象,然后通过调用迭代器对象的 next() 方法来遍历所有返回值
数组有内置的 @@iterator,因此 for..of 可以直接应用在数组上。我们使用内置的 @@iterator 来手动遍历数组
var myArray = [1,2,3]; var it = myArray[Symbol.iterator](); it.next(); // {value: 1, done: false} it.next(); // {value: 2, done: false} it.next(); // {value: 3, done: false} it.next(); // {done: true}
这里和值 ‘3’ 返回的是 done:false,咋一看好像很奇怪,你必须调用一次 next() 才能得到 done:true,从而确定完成遍历
普通的对象没有内置的 @@iterator,所以无法自动完成 for..of 遍历,当然,可以自己给任何想遍历的对象定义 @@iterator
var myObj = { a:2, b:3 } Object.defineProperty(myObj, Symbol.iterator, { enumerable: false, writable: false, configurable: true, value: function() { var o = this; var idx = 0; var ks = Object.keys(o); return { next: function() { return { value: o[ks[idx++]], done: (idx > ks.length) } } } } }) var it = myObj[Symbol.iterator](); it.next(); // {value: 2, done: false} it.next(); // {value: 3, done: false} it.next(); // {done: true}