本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
这是源码共读的第33期 | arrify 转数组,链接:arrify 转数组。
源码解读
export default function arrify(value) {
// 如果是null或者undefined,返回[]
if (value === null || value === undefined) {
return [];
}
// 如果是数组,返回原本的value
if (Array.isArray(value)) {
return value;
}
// 如果是字符串,因为字符串本身也是可迭代对象,为了保证值的完整,且避免进入下面的if判断,在这里返回[value]
if (typeof value === 'string') {
return [value];
}
// 如果是可迭代对象,通过扩展运算符(...)返回数组(扩展运算符内部是调用了Iterator接口)
if (typeof value[Symbol.iterator] === 'function') {
return [...value];
}
// 其他类型包裹在数组下即可
return [value];
}
疑惑点
1、 为什么类数组不能进行转换。
在 [issue]('https://github.com/sindresorhus/arrify/issues/2')里作者解释了不转换类数组对象的原因。
2、为什么要判断可迭代对象。
JavaScript原有的表示“集合”的数据结构,主要有数组和对象,ES6又添加了`Map`和`Set`。这就有了四种数据集合,用户还可以组合它们,定义自己的数据结构,比如数组的成员是`Map`,`Map`的成员是对象。这样就需要一种统一的接口机制,来处理不同的数据结构。
遍历器就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构,只要部署Iterator接口,就可以完成遍历操作(既依次处理该数据结构的所有成员)。
这段概念参考自 [es6]('https://es6.ruanyifeng.com/#docs/iterator')
回到问题为什么要判断可迭代对象,因为任何数据结构,只要部署Iterator接口,就可以完成遍历操作。既然能完成遍历操作,那么就能通过扩展运算符(...)将值转换为数组。
知识点
1、Iterator是什么?
它就是一种接口,为不同的数据类型提供统一的访问机制。
2、Iterator有什么作用?
- 为各种数据结构,提供一个统一的、简便的访问接口。
- 使得数据结构的成员能够按某种次序排序。
- ES6创造了一种新的遍历命令
for...of循环,Iterator接口主要提供for...of消费。 - 原生具备Iterator接口的数据结构 (Array、Map、Set、String、TypedArray、arguments对象、NodeList对象)。
3、Iterator的使用场景
- 解构赋值
const test = [1, 2, 3, 4];
const [x, ...result] = test;
console.log(x); // 1
cnosole.log(result); // [2, 3, 4]
- 扩展运算符
const iterator = 'iterator';
console.log([...iterator]); // ['i', 't', 'e', 'r', 'a', 't', 'o', 'r']
- yield后面跟着一个可遍历的结构,它会调用该结构的遍历器接口
function* genreator (){
yield 1;
yield* [2, 3, 4];
yield 5;
}
const iterator = genreator();
iterator.next(); // { done: false, value: 1}
iterator.next(); // { done: false, vlaue: 2 }
iterator.next(); // { done: flase, value: 3 }
iterator.next(); // { done: false, value: 4 }
iterator.next(); // { done: false, value: 5 }
iterator.next(); // { done: true, value: undefined }
- 由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用了遍历器接口,如
for...of
Array.form
Map()
Set()
WeakMap()
WeakSet()
Promise.all
Promise.race
4、什么是类数组对象?
- 不是数组,无法使用Array.prototype上的属性。
- 有length属性。
- 能通过索引访问。
5、类数组如何转换成数组?
const typedArray = { 0: 0, 1: 1, 2: 2, 3: 3, length: 4 }
console.log(Array.from(TypedArray)); // [0, 1, 2, 3]
6、运行npm run test ( 实际运行 “xo && ava && tsd”)
- xo 开箱即用的Linter,默认提供优质的esLint配置。
- ava 轻量高效简单易用的测试运行器,优势并行执行测试用例,执行根目录下的test.js
- tsd 类型定义文件编写测试,检测TypeScript类型声明定义,执行xxx.test-d.ts
学习所得
- Iterator是什么、有什么作用、有什么使用场景
- 巩固类数组的定义及数组转换。
- 学会通过xo & ava & tsd 实现零配置满足eslint校验、测试用例检测,测试类型定义检测。