Array.of()和Array.from()

阅读 1.6k
标签: JavaScript

ES6新增了二种方法:Array.of()Array.from(),它们有什么用途呢?

Array.of

ES6之前,有两种构建数组的方式,一种是数组字面量,一种是构造函数Array但是,构造函数在设计时存在一个缺陷(怪癖),如果只传一个数字,那么指定的是数组的长度,而不是填充的值。为了弥补这个问题,设计组没有在原有基础上直接更改,而是重新推出了一个新方法of()来解决这个问题。可以这么说,of()方法的是作为一个救火队员的身份出现的

Array.of(7);       // [7]
Array.of(1, 2, 3); // [1, 2, 3]

Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]

如上,Array(7)得到的是长度为7的数组,每一项都为空,这不符合我们的本意,我们的本意是想创建一个长度为1的数组(其中只有一项为数字类型7),但构造函数的这个缺陷(怪癖)导致了歧义,而of()方法则很好地优化了这个问题。

也许有人会说,如果一开始,构造函数Array的特征就设计得和现在的of()方法一样,或许就不需要用of()方法来弥补这个漏洞了,想法是美好的,现实是残酷的。你要知道,没有任何一门语言是完美的,尤其是对于JavaScript而言,它只用10天时间就被设计出来了!

接下来,我们再来看看Array.from()方法。

一个问题

首先,我们来看一个问题,需要创建一个共81项的数组,有9行,每行9个数(从1-9),在页面上进行展示,如下:


怎么做呢?可以这样:

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr = arr.concat(arr)
arr = arr.concat(arr)
arr = arr.concat(arr)
arr = arr.concat([1, 2, 3, 4, 5, 6, 7, 8, 9])

console.table(arr)

的确可以实现,但是真的不优雅,一种欠薪程序员的风格扑面而来!如果规模加大,需要的是810项的数组呢?那就需要换一种方式实现了:

let arr = Array.apply(null, { length: 810 })
  .map((item, index) => {
    return {
      id: index,
      number: index % 9 + 1
    }
  })

看上去是不错,但容易让人困惑,阅读起来很不直观,又是apply,又是null的,让人抓狂。

我们试试用ES6的Array.from

let arr = Array.from({ length: 810 }, (item, index) => ({
  id: index,
  number: index % 9 + 1
}))

代码量变少了,更重要的是,代码意图也更直观了,数组长度810,每一项按照约定的规则进行初始化。

注意:{length: 810}是一个类数组对象。

Array.from

相信大家已经对from()有了大概的了解了,准确说,Array.from()方法对一个类数组可迭代对象创建一个新的,浅拷贝的数组实例。因为其本身是通过转化其他对象来获得数组的,所以,这个from命名倒是恰到好处。

我们来看看它的语法:

Array.from(arrayLike[, mapFn[, thisArg]])

arrayLike:想要转换成数组的伪数组对象或可迭代对象。

mapFn(可选):如果指定了该参数,新数组中的每个元素会执行该回调函数。

thisArg(可选):执行回调函数 mapFn 时 this 对象。

因此,可以通过以下方式来创建数组对象:

  • 伪数组对象(拥有一个length属性和若干索引属性的任意对象)
  • 可迭代对象(可以获取对象中的元素,如 Map和 Set 等)

上面那个例子中,就是通过包含length属性的伪数组对象,来构建了一个长度810的数组。

我们再来看看通过可迭代对象构建数组的例子:

const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set);
// [ "foo", "bar", "baz" ]

上面的set变量时一个可迭代对象,最终通过Array.from()获得了数组。

小结

所以说,Array.of()是对构造数组Array的优化,而Array.from()则是将伪数组对象或者可迭代对象转化为数组。

参考

最后编辑于: 2022-06-28

评论(0条)

(必填)
复制成功