本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
本期的源码仓库在此: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];
}
这个函数对传入的参数使用了多个if判断来提高代码的健壮性,并使用全等运算符===来解决非全等运算符产生的数据类型隐式转换问题
首先判断传入的参数是不是null或者undefined,满足条件的话就直接返回空数组。对于undefined的判断,我在eslint的规则文档no-void和underscore源码解读文章当中得知,在函数的局部作用域当中可以用声明变量的方式来改写undefined的值,而void 0不能被重写,而且还能少几个字符。因此推荐使用void 0.
(function(){
var undefined = 12;
console.log(undefined); //12
})();
然后在用es6的新语法Array.isArray来判断参数类型是不是数组。相比比Object.prototype.toString.call,这个方法更简单。
接下来判断参数类型是不是字符串,作者的倾向是直接返回一个含有这个字符串的数组,而不是分割成字符数组。
再接下来就是判断参数是不是实现了Iterator接口。Symbol是es6新增的原始类型,表示独一无二的值。Symbol.iterator是内置的Symbol值。实现了Iterator接口的对象可以对其进行for...of遍历,也可以使用展开运算符...进行解构。实现了Iterator接口有String、Array、Arguments和NodeList等类型。我会在以后的文章当中详细的写一下Iterator的内容,在此不再赘述。
回到代码,作者对实现了Iterator接口的数据(除了Array)使用了展开运算符,并放在一个数组里面。相比Array.prototype.slice.call,这个方法更简单。
最后,如果参数的类型不满足上面的任何判断条件,就放在一个数组里面。