arrify 转数组

85 阅读2分钟

本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。

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 循环遍历的本质是:

  1. for..of 循环首先会调用对象上的方法属性 [Symbol.iterator]——rangeSymbol.iterator,得到一个包含 next 方法的对象。 ○ 这个包含 next 方法的对象称为迭代对象(iterator object) ○ 属性 range[Symbol.iterator] 被称为迭代对象生成器或迭代对象生成函数
  2. 接下来, for..of 就是完全在跟这个迭代对象打交道了,
  3. 每次 for..of 循环一次,就要调用一次 next 方法,
  4. 从 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()