本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
// 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提前拿出来判断。
总体来说,思考比较简单,重要的是在看源代码的时候多想想为什么这么写,试着提出自己的解决方案。