定义
两者都是遍历的方法,最先能想到的区别是,前者是遍历键名,后者是遍历键值。
看一下两者的定义:- for...in 遍历当前对象的所有可枚举属性(包括自有属性,从原型继承的属性),遍历顺序是无序的
- for...of 遍历当前可遍历(iterable)数据结构拥有的可迭代元素(iterator),是有序的,是ES6提供的新方法
那么iterator是什么呢
遍历器 iterator
iterator是一种接口,为不同的数据结构提供统一的访问机制。
iterator主要供for...of消费。一种数据结构只要部署了iterator接口,就称之为可遍历的。ES6中提供了一些具备原生iterator接口的数据结构(包括Array、Map、Set、String、TypedArray、函数的arguments对象、NodeList对象。不包括Object),部署在数据结构的Symbol.iterator属性中。所以也可以说,一种数据结构只要有Symbol.iterator属性,就称之为可遍历的。var myIterable = {};myIterable[Symbol.iterator] = function* () { yield 1; yield 2; yield 3;};for (let value of myIterable) { console.log(value); }// 1// 2// 3
for...of使用示例
// 遍历数组let iterable = [10, 20, 30];for (let value of iterable) { value += 1; console.log(value);}// 11// 21// 31// 遍历字符串let iterable = 'boo';for (let value of iterable) { console.log(value);}// "b"// "o"// "o"// 遍历Maplet iterable = new Map([['a', 1], ['b', 2], ['c', 3]]);for (let entry of iterable) { console.log(entry);}// ['a', 1]// ['b', 2]// ['c', 3]for (let [key, value] of iterable) { console.log(value);}// 1// 2// 3// 遍历arguments(function() { for (let argument of arguments) { console.log(argument); }})(1, 2, 3);// 1// 2// 3
如果用中断for...of,可以使用break、continue、throw或return
function* foo(){ yield 1; yield 2; yield 3; }; for (let o of foo()) { console.log(o); break; // 终止iterator,跳出循环}
for...in使用示例
// 从原型继承的属性Object.prototype.objCustom = function() {}; Array.prototype.arrCustom = function() {};// 自定义属性let iterable = [3, 5, 7];iterable.foo = 'hello'; for (let i in iterable) { console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom"}for (let i in iterable) { if (iterable.hasOwnProperty(i)) { console.log(i); // 0, 1, 2, "foo" }}for (let i of iterable) { console.log(i); // 3, 5, 7}