Array.from()
Array.from()
Array.from() 是 ES6 语法中的 api, 并不像它的同窗们受人青睐,但在一些特别的用法上 出乎意料的方便和实用
定义
1 | Array.from(arrayLike[, mapFunction[, thisArg]]) |
- arrayLike:必传参数,想要转换成数组的伪数组对象(以 dom 节点为代表)或可迭代对象。
- mapFunction:可选参数,mapFunction(item,index){…} 是在集合中的每个项目上调用的函数。返回的值将插入到新集合中。
- thisArg:可选参数,执行回调函数 mapFunction 时 this 对象。这个参数很少使用。
1 | // 让我们将类数组的每一项乘以 2: |
将类数组转换成数组
js 中常见的类数组对象:函数的 arguments 关键字, DOM 节点的集合。
1 | function sumArguments() { |
克隆一个数组
Array.from() 可以很容易的实现数组的浅拷贝。
当然这里的 Array.from()在日常开发中是不如”…”(Spread syntax)的
1 | const numbers = [3, 6, 9]; |
Array.from(numbers) 创建了对 numbers 数组的浅拷贝,numbers === numbersCopy 的结果是 false,
意味着虽然 numbers 和 numbersCopy 有着相同的项,但是它们是不同的数组对象。
于是我们可以使用 Array.from 进行多维数组的递归形深拷贝;
即: 数组的情况下调用函数,其他情况直接返回
1 | function recursiveClone(val) { |
使用初始值填充数组 Array.from() vs fill
基本值
1 | const fillArray = (init, arrLen) => Array.from({ length: arrLen }, () => init); |
可以看见在基本值的情况下二者的输出几乎没有区别
但 fill 显然更加的简单;
引用值
1 | const length = 3; |
如果只看 resultA 和 resultB 的输出 好像也没有什么区别 但是
由 Array.from 返回的 resultA 是使用不同空对象实例进行初始化得到的。
之所以发生这种情况是因为每次调用时,mapFunction,即此处的 () => ({}) 都会返回一个新的对象。
但 fill() 方法创建的 resultB 是使用相同的空对象实例进行多次填充初始化。
1 | const a = { b: 2 }; |
由此可见 fill 引用值所得到的确实是同一个引用值
只是执行时为多次执行 类比于 forEach()
而这时候一旦一个值改变都将影响所有的引用 从而导致意外的值
Array.map()
1 | const length = 3; |
map() 创建出来的数组不是预期的 [0, 0, 0],而是一个有 3 个空项的数组。
这是因为 Array(length) 创建了一个有 3 个空项的数组(也称为稀疏数组),但是 map() 方法会跳过空项。
生成数字范围
1 | function range(end) { |
在 range() 函数中,Array.from() 提供了类似数组的 {length:end} ,以及一个简单地返回当前索引的 map 函数 。这样你就可以生成值范围。
数组去重
1 | function unique(array) { |
由于 Array.from() 的入参是可迭代对象,因而我们可以利用其与 Set 结合来实现快速从数组中删除重复项。
首先,new Set(array) 创建了一个包含数组的集合,Set 集合会删除重复项。
因为 Set 集合是可迭代的,所以可以使用 Array.from() 将其转换为一个新的数组。
这样,我们就实现了数组去重。当然这里的 Array.from()是不如”…”(Spread syntax)的
结论
Array.from() 方法接受类数组对象以及可迭代对象,它可以接受一个 map 函数,
并且,这个 map 函数不会跳过值为 undefined 的数值项.
因此在需要填充数据的情况下 Array.from()完胜 map() 而填充基本值时不如 fill(),
但填充引用值的时候好于 fill
参考来源:
作者:刘小夕
链接:https://juejin.cn/post/6844903926823649293
来源:掘金