Array.apply生成数组小结

发现问题

今天在学习vue时,在文档的一个例子中发现一个代码片断javascript

Array.apply(null, { length: 20 }).map(function () {
    return createElement('p', 'hi')
  })
  // 目的是为了建立一个20次的循环
复制代码

这让我想起来以前在学习中写demo时,想要用forEach来作一个若干次的循环(以为写for循环麻烦),当时是这样写的vue

Array(10).forEach(function(){
    // do something
  })
复制代码

结果是并不会进入循环,后来查询mdn缘由以下:java

forEach 方法按升序为数组中含有效值的每一项执行一次callback 函数,那些已删除(使用delete方法等状况)或者未初始化的项将>>被跳过(但不包括那些值为 undefined 的项)(例如在稀疏数组上)。es6

划重点: 未初始化的项将被跳过api

原来由于经过 Array(10) 或者 new Array(10) 方式建立的数组是一个有length属性的空数组,其中的每一个元素尚未被赋值(初始化),因此会变forEach map 等方法跳过数组

Array(10) // [empty × 10] length: 10
  new Array(10) // [empty × 10] length: 10
复制代码

解决问题

可是经过今天看到的这个方法就能够建立一个能够被forEach等方法遍历的数组,这是为何呢?app

// 这三个方法返回的是一个长度为10的数组,且每个元素都被赋值成undefined
  Array.apply(null, {length: 10}) 
  Array.apply(null, Array(10)) 
  Array.apply(null, new Array(10)) 

  // [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]
复制代码

这里先复习一下Array构造函数的用法,下面是mdn的引用函数

Array 构造器会根据给定的元素建立一个 JavaScript 数组, 可是当仅有一个参数且为数字时除外: 一个范围在 0 到 232-1 之间的整数, 此时将返回一个 length 的值等于 arrayLength 的数组对象(言外之意就是该数组此时并无包含任何实际的元素, 不能理所固然地认为它包含 arrayLength 个值为 undefined 的元素)。 注意,后面这种状况仅适用于用 Array 构造器建立数组,而不适用于用方括号建立的数组字面量。学习

划重点 可是当仅有一个参数且为数字时,组此时并无包含任何实际的元素,不能理所固然地认为它包含 arrayLength 个值为 undefined 的元素 就是说建立出来的数组中的元素并无被赋值(初始化)ui

而后再复习一下Array.apply方法的使用

Array.apply() 方法接收两个参数, 第一个为调用时指定的上下文(context); 第二个为一个数组或者一个类数组对象;

Array.apply(null, {length: 10})
  Array.apply(null, Array(10))
  Array.apply(null, new Array(10))

  // 这三个方法至关于

  Array(undefined, undefined, undefined, ...)
复制代码

由于Array构造函数会根据给定的arguments来建立一个数组(若是不是仅有一个参数且为数字的话), 经过Array.apply传入一个length为10的空数组则至关于, 把一个空数组中的每个元素的值逐个传入Array()方法, 而空数组中的每个元素 好比: emptyArr[0] 的值都是 undefined

为了便于理解这里写一个伪代码; 伪代码:

var arrayLike = {length: 2}
          ↓↓
  Array.apply(null, arrayLike)
          ↓↓
  Array(arrayLike[0], arrayLike[1]) // 把一个空数组中的每个元素的值逐个传入Array()方法
          ↓↓
  Array(undefined, undefined) // 而空数组中的每个元素的值都为undefined

  //最终输出 [undefined, undefined]
复制代码

这也就是为何能够经过Array.apply()方法能够生成一个可供forEach等方法遍历的数组

Array.apply(null, {length: 5}) 
  // 上面这样写实际上等于下面这样写
  Array(undefined, undefined, undefined, undefined, undefined)

  // [undefined, undefined, undefined, undefined, undefined]
  // 生成的数组里的元素都被初始化成了undefined,就能够被forEach等方法遍历了
复制代码

另外es6提供了一个新的api,Array.from()也能够作到相同的结果

如下是阮一峰老师的《ECMAScript 6 入门》的引用

Array.from方法还支持相似数组的对象。所谓相似数组的对象,本质特征只有一点,即必须有length属性。所以,任何有length属性的>对象,均可以经过Array.from方法转为数组

Array.from({length: 5})
  // [undefined, undefined, undefined, undefined, undefined]
复制代码

es6的另外一种写法

Array(...Array(5))
  // 或者
  [...Array(10)]
  // [undefined, undefined, undefined, undefined, undefined]
复制代码
相关文章
相关标签/搜索