javascript - js数组初始化 - lodash创建数组




如何在javascript中初始化数组的长度? (11)

我在JavaScript中读过的大部分教程(包括w3schoolsdevguru )都表明,您可以使用var test = new Array(4);将一个整数传递给Array构造函数,从而初始化一个具有特定长度的数组var test = new Array(4); 句法。

在我的js文件中大量使用这个语法后,我通过jsLint运行了一个文件,它吓坏了:

错误:第1行字符22处的问题:预期')',而是看到'4'。
var test = new Array(4);
第1行字符23处的问题:预期';' 而是看到')'。
var test = new Array(4);
第1行字符问题23:预期标识符,而是看到')'。

在阅读jsLint对其行为的解释之后 ,它看起来像jsLint并不真正喜欢new Array()语法,而是在声明数组时更喜欢[]

所以我有几个问题。 首先,为什么? 我是否使用new Array()语法来运行任何风险? 是否有浏览器不兼容,我应该知道? 第二,如果我切换到方括号语法,是否有任何方法来声明一个数组并将其长度全部设置为一行,或者我必须这样做:

var test = [];
test.length = 4;

  1. 你为什么要初始化长度? 理论上这是没有必要的。 它甚至可能导致混淆行为,因为所有使用length来查找数组是否为空的测试都会报告数组不为空。
    Some tests表明,如果数组之后被填充,设置大型数组的初始长度可以更有效,但是性能增益(如果有的话)似乎因浏览器而异。

  2. jsLint不喜欢new Array()因为constructer是不明确的。

    new Array(4);
    

    创建一个长度为 4的空数组

    new Array('4');
    

    创建一个包含值 '4'的数组。

关于你的评论:在JS中,你不需要初始化数组的长度。 它动态增长。 您可以将该长度存储在某个变量中,例如

var data = [];
var length = 5; // user defined length

for(var i = 0; i < length; i++) {
    data.push(createSomeObject());
}

ES6引入了Array.from ,它允许您从任何“类似数组”可迭代对象创建一个Array

Array.from({length: 10}).map((x, i) => i);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

在这种情况下, {length: 10}表示一个“类似数组”的对象的最小定义:一个只有length属性定义的空对象。


如上所述,使用new Array(size)有点危险。 不要直接使用它,将它放在“数组创建器函数”中。 您可以轻松确保此功能无缺陷,并且避免了直接调用new Array(size)的风险。 此外,你可以给它一个可选的默认初始值。 这个createArray函数的确如此:

function createArray(size, defaultVal) {
    var arr = new Array(size);
    if (arguments.length == 2) {
        // optional default value
        for (int i = 0; i < size; ++i) {
            arr[i] = defaultVal;
        }
    }
    return arr;
}

您可以使用array.length = youValue来设置数组长度

所以它会

var myArray = [];
myArray.length = yourValue;

数组构造函数有一个模糊的语法 ,而JSLint只是伤害了你的感受。

此外,您的示例代码已损坏,第二个var语句将引发一个SyntaxError 。 你正在设置数组test的属性length ,所以不需要另一个var

就你的选择而言, array.length是唯一的“干净”的。 问题是,为什么你需要首先设置大小? 尝试重构你的代码来摆脱这种依赖。


最短的:

[...Array(1000)]

请人们不要放弃你过去的习惯。 在分配内存一次,然后使用该数组中的条目(如旧)一样,并且随着数组增长而分配多次(这不可避免地是系统在其他建议的方法下进行的) 。

当然,这些都不重要,除非你想用更大的数组做一些很酷的事情。 然后它确实。

目前来看,JS似乎还没有选择设置数组的初始容量,我使用以下...

var newArrayWithSize = function(size) {
  this.standard = this.standard||[];
  for (var add = size-this.standard.length; add>0; add--) {
   this.standard.push(undefined);// or whatever
  }
  return this.standard.slice(0,size);
}

有涉及的权衡:

  • 此方法与第一次调用函数时所用的方法一样长,但稍后调用的时间很少(除非要求更大的数组)。
  • standard阵列会永久保留您所要求的最大阵列的空间。

但是,如果它符合你所做的事情,那么可能会有收益。 非正式的时间表

for (var n=10000;n>0;n--) {var b = newArrayWithSize(10000);b[0]=0;}

在相当快的速度下(大约50ms的10000给出了n = 1000000大约需要5秒钟)

for (var n=10000;n>0;n--) {
  var b = [];for (var add=10000;add>0;add--) {
    b.push(undefined);
  }
}

在一分钟之内(对于在同一个Chrome控制台上的10000个大约90秒,或者大约2000倍慢)。 这不仅仅是分配,还包括10000推,for循环等。


这个代码演示了你不应该使用new Array的原因:

var Array = function () {};

var x = new Array(4);

alert(x.length);  // undefined...

其他一些代码可能会混淆Array变量。 我知道这有点牵强,任何人都会写这样的代码,但仍然...

另外,正如Felix King所说,界面有点不一致,并且可能导致一些非常难以追踪的错误。

如果你想要一个长度为= x的数组,并且填充了未定义的new Array(x)new Array(x) ),你可以这样做:

var x = 4;
var myArray = [];
myArray[x - 1] = undefined;

alert(myArray.length); // 4

这是另一种解决方案

var arr = Array.apply( null, { length: 4 } );
arr;  // [undefined, undefined, undefined, undefined] (in Chrome)
arr.length; // 4

apply()的第一个参数是一个这个对象绑定,我们在这里不关心,所以我们将它设置为null

Array.apply(..)正在调用Array(..)函数并展开{ length: 3 }对象值作为其参数。


[...Array(6)].map(x=>0);

// [0, 0, 0, 0, 0, 0]

要么

Array(6).fill(0);

// [0, 0, 0, 0, 0, 0]

要么

Array(6).fill(null).map( (x,i) => i );

// [0, 1, 2, 3, 4, 5]

打字稿安全

创建嵌套数组

直观地用fill创建二维数组时,应该创建新的实例。 但实际发生的是相同的数组将作为参考存储。

var a = Array(3).fill([6]); 
// [[6], [6], [6]]

a[ 0 ].push( 9 );
// [[6,9], [6,9], [6,9]]

var a = [...Array(3)].map(x=>[]); 

a[ 0 ].push( 4, 2 );
// [[4,2], [ ], [ ]]

所以3x2阵列看起来像这样:

[...Array(3)].map(x=>Array(2).fill(0));

// [ [0,0] ,
//   [0,0] ,
//   [0,0] ]

  • Array(5)给你一个长度为5但没有值的数组,因此你不能迭代它。

  • Array.apply(null, Array(5)).map(function () {})为您提供长度为5 Array.apply(null, Array(5)).map(function () {})定义为值的数组,现在可以迭代。

  • Array.apply(null, Array(5)).map(function (x, i) { return i; })给你一个长度为5,值为0,1,2,3,4的数组。

  • Array(5).forEach(alert)什么都不做, Array.apply(null, Array(5)).forEach(alert)给你5个警报

  • ES6给了我们Array.from现在你也可以使用Array.from(Array(5)).forEach(alert)

  • 如果你想用特定的值进行初始化,这些知识是很好的...
    Array.from('abcde')Array.from('x'.repeat(5))
    Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]







jslint