[若川视野 x 源码共读] 第33期 | arrify

182 阅读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];
}

这个函数对传入的参数使用了多个if判断来提高代码的健壮性,并使用全等运算符===来解决非全等运算符产生的数据类型隐式转换问题

首先判断传入的参数是不是null或者undefined,满足条件的话就直接返回空数组。对于undefined的判断,我在eslint的规则文档no-voidunderscore源码解读文章当中得知,在函数的局部作用域当中可以用声明变量的方式来改写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,这个方法更简单。

最后,如果参数的类型不满足上面的任何判断条件,就放在一个数组里面。