将 Array.map 与新的 Array 构造函数一起使用

Using Array.map with new Array constructor

我试图将 new Array() 构造函数与 map 一起使用,以便创建一个创建元素列表的单行代码。像这样:

let arr = new Array(12).map( (el, i) => {
  console.log('This is never called');
  return i + 1;
});

阅读docs,这种行为是有道理的。

Basically docs say that callback of map will be executed even for declared undefined values in array, but not for example when creating empty Arrays like the code before.

所以这应该有效:

var arr = new Array(12);

for(let i = 0; i < arr.length ; i++){
  arr[i] = undefined;
}

let list = arr.map( (e, i) => {
  console.log(i + 1);
  return i + 1;
});

所以,我们也可以这样做:

let newArray = (length) => {
  let myArray = new Array(length);
  for(let i = 0; i < length; i++) myArray[i] = undefined;
  return myArray;
};

console.log( newArray(12).map( (el, i) => i + 1 ) );

所以我的问题。有没有 better/pretty 方法可以用 map 函数做到这一点?

提前致谢!

您可以使用Array#from创建一个超过长度的数组。

Array.from({length: 12}, (e, i) => i + 1);

Section 22.1.3.15 of the spec 得到了你,最后一行 NOTE 1:

callbackfn is called only for elements of the array which actually exist; it is not called for missing elements of the array.

此行为由 filterforEach 和其他功能方法共享。

您正在调用的数组构造函数 Array(len) 来自 section 22.1.1.2,将设置数组的长度但不会初始化元素。我不确定规范在哪里定义缺少的元素是什么,但是 new Array(len) 生成的数组应该适合那个,因此 none 的元素将被 map.

我喜欢这种方法,因为它在 ES5 中仍然有效:

let arr = Array.apply(null, Array(12))
    .map(function (x, i) {
        return i
    });

// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

因为 New Array returns 一个包含 "holes" 的数组,我们使用 apply 因为 apply 将空洞视为未定义。这将 undefined 分布在整个数组中,使其可映射。

您可以将 Array.apply 与其中包含长度的对象一起使用。

var array = Array.apply(null, { length: 12 }).map((_, i) => i + 1);
console.log(array);

如果我没记错的话,你明确表示你想要 new Array 构造函数的答案。

这是操作方法。一行,漂亮的ES6:

let me = [...new Array(5)].map((x,i)=>i)
// [0,1,2,3,4]

解释:

  1. new Array(5) 生成这个:[ , , , , ]​​​​​
  2. [...new Array(5)] 是 shorthand 对应 Array.from(new Array(5)), 并生成这个:​​​​​[ undefined, undefined, undefined, undefined, undefined ]​​​​​,这是一个 undefined 的数组 对象。是的,undefined 是一个值(原始值 :))。
  3. 现在我们可以迭代我们全新数组的值:D

PS:您甚至可以跳过 new 关键字并执行:

[...Array(5)].map((x,i)=>i)