本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
index.js中内容
export default function arrify(value) {
// 如果value是null或者undefined 返回[]
if (value === null || value === undefined) {
return [];
}
if (Array.isArray(value)) {
return value;
}
// 如果value是strinf类型 返回[value] e.g. 'nihao' => ['nihao']
if (typeof value === 'string') {
return [value];
}
// 重点来喽
if (typeof value[Symbol.iterator] === 'function') {
return [...value];
}
return [value];
}
Symbol.iterator 是可迭代对象的一个属性
可迭代对象
概览
- 可迭代对象不一定是数组,数组一定是可迭代对象。
- 可迭代对象必定包括一个[Symbol.iterator]方法属性。
- 字符串也是可迭代对象(主要是字符串有[Symbol.iterator]方法属性)
- 每个可迭代对象都有一个 [Symbol.iterator] 方法属性,没有的话,肯定不是可迭代对象。
改造普通对象
let obj = {
from: 1,
to: 5
}
想让obj 通过 forof 循环遍历 且结果为1 2 3 4 5
Symbol.iterator 介绍
let obj = {
from: 1,
to: 5
}
// 1. for..of 循环首先会调用对象上的 [Symbol.iterator] 属性——range[Symbol.iterator]()【被叫做迭代对象生成器或迭代对象生成函数】
obj[Symbol.iterator] = function() {
// 2. forof 会返回一个包含 next 方法的对象 该对象被称为迭代对象
return {
current : this.from,
to : this.to,
// 3.每次forof 就会调用一次next方法
next() {
if (this.current <= this.to) {
// 4. 从 next 方法返回的对象中,我们能获得当前遍历的值(value)以及遍历是否结束的标记(done
return {done:false,value:this.current++}
}else {
return {done:true}
}
}
}
}
for (const iterator of obj) {
console.log(iterator);
}
for...of 循环遍历的本质是:
- for..of 循环首先会调用对象上的方法属性 [Symbol.iterator]——rangeSymbol.iterator,得到一个包含 next 方法的对象。 ○ 这个包含 next 方法的对象称为迭代对象(iterator object) ○ 属性 range[Symbol.iterator] 被称为迭代对象生成器或迭代对象生成函数
- 接下来, for..of 就是完全在跟这个迭代对象打交道了,
- 每次 for..of 循环一次,就要调用一次 next 方法,
- 从 next 方法返回的对象中({ done: ..., value: ... }),我们能获得当前遍历的值(value)以及遍历是否结束的标记(done)。
经过上面的叙述,我们还可以将可迭代对象定义为:能够生成“迭代对象”的对象
手写遍历可迭代对象
let iterator = obj[Symbol.iterator]()
let res = iterator.next()
while (true) {
if (res.done) break
return res.value
}
常见的可迭代对象
数组、字符串、map、set
Map 对象默认的迭代对象生成器函数是 map.entries() Set 对象默认的迭代对象生成器函数是 map.values()