探索问题:
- 为什么ES6中数组,字符串等是可迭代的,而对象却是不可迭代?直观感受就是数组和字符串都可以用
for...of,而对象却不可以。
- 实现一个最小化的迭代器。
JavaScript中可以迭代的两种情景:
- 程序层级:检测程序的结构
- 数据层级:检测程序中所有的数据
这两个层级过于抽象,尤其是程序层级,可以借助js中的数组来理解:
1 2 3 4 5 6
| const dt = [1,2,3,4]; // 数据层 dt.func = () => {}; // 程序层
for (let i in dt) console.log(xs[i]); // 1, 2, 3, 4, () => {}
for (let i of dt) console.log(i); // 1, 2, 3, 4
|
像ES5中的for...in可以检测对象中的所有属性,针对的大多数就是程序层级。为了解决这个问题,ES6中引入了for...of.
那既然可以用for...in遍历对象,为何就不能用for...of了?
如果设计可以迭代对象,也就意味着会混淆上面两个层级,简单的理解就是一个对象不可能仅仅只是像数组一样存储一组数据。如果混合上述两个概念,也就是说可以使用for...of遍历对象,意味着只能遍历对象的数据,而不能遍历其他程序层级的属性,相当于把对象当成一个数据层级来处理,这很可能会破坏代码结构。
为了解决对象不可以使用for...of遍历的问题,ES6中引入了一个新的概念Map,使用Map创建的key-value对就可以迭代遍历。
当然也可以做一个工具函数,来实现对对象的迭代。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| function objectEntries(obj) { let index = 0;
const propKeys = Reflect.ownKeys(obj);
return { [Symbol.iterator]() { return this; }, next() { if (index < propKeys.length) { const key = propKeys[index]; index++; return { value: [key, obj[key]] }; } else { return { done: true }; } } }; }
const obj = { first: 'Jane', last: 'Doe' }; for (const [key,value] of objectEntries(obj)) { console.log(`${key}: ${value}`); }
|
PS.可以思考一下为什么不扩充在Object原型链上?
扩展阅读
- Plain objects are not iterable
- Why are Objects not Iterable in JavaScript?