Smilence | 第18分组 | 第33期 | arrify 转数组

147 阅读2分钟

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

// arrify源代码
export default function arrify(value) {
	if (value === null || value === undefined) {
		return [];
	}

	if (Array.isArray(value)) {
		return value;
	}

	if (typeof value === 'string') {
		return [value];
	}

	if (typeof value[Symbol.iterator] === 'function') {
		return [...value];
	}

	return [value];
}

代码较简单,基本功能就是将输入的值转换为数组形式返回,在此过程中不会改变传入值本身。

关于代码本身的分析其他同学已经有很多帖子,我这里讲一下我比较关注的点。

重点的部分从第十行开始。 可以看到当 value === 'string' 和第18行代码最后返回时的返回值都是[value]。很自然的想法就是,为什么不把这两者合并呢?这样就可以不需要单独判断string了,合并后的代码如下:

// 自定义arrify_1
export default function arrify(value) {
	if (value === null || value === undefined) {
		return [];
	}

	if (Array.isArray(value)) {
		return value;
	}

	if (typeof value[Symbol.iterator] === 'function') {
		return [...value];
	}

	return [value];
}

很显然上面的代码是行不通的,而答案就在第14行引入的判断 typeof value[Symbol.iterator] === 'function' ,这条语句就是在判断传入值是否可以用 ... 解构,能够用 ... 解构的结构包括:(引自www.yuque.com/docs/share/…

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函数的 arguments 对象
  • NodeList 对象

可以看到, string 也在其中,如果不将string单独拿出来判断,那么代码会走到代码块自定义arrify_1中的第11行,而在对string进行解构时,其行为如下:

string中的每个字符会被拎出来作为数组返回,这通常不是我们想要的,因此需要将string提前拿出来判断。

总体来说,思考比较简单,重要的是在看源代码的时候多想想为什么这么写,试着提出自己的解决方案。