如何在JavaScript中初始化数组的长度?

2020/09/24 04:41 · javascript ·  · 0评论

我阅读过的有关JavaScript数组的大多数教程(包括w3schoolsdevguru)都建议您可以通过使用var test = new Array(4);语法将整数传递给Array构造函数来初始化具有一定长度的数组

在我的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来查明数组是否为空的测试都会报告该数组不为空。
    一些 试验表明,设定大的阵列的初始长度可以如果该阵列被充满之后更有效,但性能增益(如果有的话)似乎不同于浏览器的浏览器。

  2. jsLint不喜欢,new Array()因为构造方法不明确。

    new Array(4);

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

    new Array('4');

    创建一个包含value 的数组'4'

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

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

for(var i = 0; i < length; i++) {
    data.push(createSomeObject());
}
  • Array(5) 给您一个长度为5但没有值的数组,因此您无法对其进行迭代。

  • Array.apply(null, Array(5)).map(function () {}) 给您一个长度为5且未定义为值的数组,现在可以对其进行迭代。

  • 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]

借助ES2015,.fill()您现在可以轻松执行以下操作:

// `n` is the size you want to initialize your array
// `0` is what the array will be filled with (can be any other value)
Array(n).fill(0)

比这简明得多 Array.apply(0, new Array(n)).map(i => value)

可以插入0in .fill()并在不使用参数的情况下运行,这将用填充数组undefined但是,这将在Typescript中失败

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

要么

Array(6).fill(0);
// [0, 0, 0, 0, 0, 0]

注意:您不能循环空插槽,即 Array(4).forEach(() => …)


要么

打字稿安全

Array(6).fill(null).map((_, i) => i);
// [0, 1, 2, 3, 4, 5]

要么

使用函数的经典方法(可在任何浏览器中使用)

function NewArray(size) {
    var x = [];
    for (var i = 0; i < size; ++i) {
        x[i] = i;
    }
    return x;
}

var a = NewArray(10);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

创建嵌套数组

直观地创建2D数组时,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]  ]

N维数组

function NArray(...dimensions) {
    var index = 0;
    function NArrayRec(dims) {
        var first = dims[0], next = dims.slice().splice(1); 
        if(dims.length > 1) 
            return Array(dims[0]).fill(null).map((x, i) => NArrayRec(next ));
        return Array(dims[0]).fill(null).map((x, i) => (index++));
    }
    return NArrayRec(dimensions);
}

var arr = NArray(3, 2, 4);
// [   [  [ 0,  1,  2,  3 ] , [  4,  5,  6,  7]  ],
//     [  [ 8,  9,  10, 11] , [ 12, 13, 14, 15]  ],
//     [  [ 16, 17, 18, 19] , [ 20, 21, 22, 23]  ]   ]

初始化棋盘

var Chessboard = [...Array(8)].map((x, j) => {
    return Array(8).fill(null).map((y, i) => {
        return `${String.fromCharCode(65 + i)}${8 - j}`;
    });
});

// [ [A8, B8, C8, D8, E8, F8, G8, H8],
//   [A7, B7, C7, D7, E7, F7, G7, H7],
//   [A6, B6, C6, D6, E6, F6, G6, H6],
//   [A5, B5, C5, D5, E5, F5, G5, H5],
//   [A4, B4, C4, D4, E4, F4, G4, H4],
//   [A3, B3, C3, D3, E3, F3, G3, H3],
//   [A2, B2, C2, D2, E2, F2, G2, H2],
//   [A1, B1, C1, D1, E1, F1, G1, H1] ]

最短的:

let arr = [...Array(10)];
console.log(arr);

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

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

在这种情况下,{length: 10}代表了“数组状”对象的最小定义:一个仅length定义属性的空对象

Array.from 允许第二个参数映射到结果数组上。

这会将length属性初始化为4:

var x = [,,,,];

令我惊讶的是,还没有一个功能性的解决方案可以让您在一行中设置长度。以下基于UnderscoreJS:

var test = _.map(_.range(4), function () { return undefined; });
console.log(test.length);

由于上述原因,除非我想将数组初始化为特定值,否则我将避免这样做。有趣的是,还有其他实现范围的库,包括Lo-dash和Lazy,它们可能具有不同的性能特征。

请人们暂时不要放弃您的旧习惯。在分配内存一次然后使用该数组中的条目(较旧)与随着数组增长对其进行多次分配之间,速度存在很大差异(这不可避免地是系统在使用其他建议方法的情况下所做的工作) 。

当然,这一切都无关紧要,除非您想对更大的阵列做一些很棒的事情。然后就可以了。

鉴于目前在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;}

以相当快的速度(对于10000,大约需要50ms,因为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循环等。

(这可能是更好的评论,但时间太长了)

因此,看完这篇文章后,我很好奇预分配实际上是否更快,因为从理论上讲应该如此。但是,此博客提供了一些建议,建议不要使用http://www.html5rocks.com/en/tutorials/speed/v8/

因此仍然不确定,我将其进行了测试。事实证明,它似乎实际上要慢一些。

var time = Date.now();
var temp = [];
for(var i=0;i<100000;i++){
    temp[i]=i;
}
console.log(Date.now()-time);


var time = Date.now();
var temp2 = new Array(100000);
for(var i=0;i<100000;i++){
    temp2[i] = i;
}
console.log(Date.now()-time); 

几次随意运行后,此代码将产生以下内容:

$ node main.js 
9
16
$ node main.js 
8
14
$ node main.js 
7
20
$ node main.js 
9
14
$ node main.js 
9
19
var arr=[];
arr[5]=0;
alert("length="+arr.length); // gives 6

这是另一种解决方案

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

的第一个参数apply()是this对象绑定,此处我们不在乎,因此将其设置为null

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

假设数组的长度是恒定的。在Javascript中,这是我们的工作:

const intialArray = new Array(specify the value);

数组构造函数的语法不明确,毕竟JSLint只会伤害您的感觉。

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

就您的选择而言,array.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;
}

在大多数答案中,建议将其推荐给fill数组,因为否则“您不能对其进行迭代”,但这不是事实。您可以迭代一个空数组,而不必使用forEachWhile循环,for循环和for i循环工作正常。

const count = Array(5);

不起作用。

console.log('---for each loop:---');
count.forEach((empty, index) => {
    console.log(`counting ${index}`);
});

这些工作:

console.log('---for of loop:---');
for (let [index, empty] of count.entries()) {
  console.log(`counting for of loop ${index}`);
}

console.log('---for i loop:---');
for (let i = 0, il = count.length; i < il; ++i) {
  console.log(`counting for i loop ${i}`);
}

console.log('---while loop:---');
let index = 0;
while (index < count.length) { 
  console.log(`counting while loop ${index}`); 
  index++; 
}

用上面的例子检查这个小提琴

角度也*ngFor适用于空数组:

<li *ngFor="let empty of count; let i = index" [ngClass]="
  <span>Counting with *ngFor {{i}}</span>
</li>

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

原来如此

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

new Array此代码演示了不应该使用的原因

var Array = function () {};

var x = new Array(4);

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

其他一些代码可能会使Array变量混乱。我知道有人会写这样的代码有点牵强,但是...

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

如果您想要一个长度为x的数组,并用未定义填充(new Array(x)将这样做),则可以执行以下操作:

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

alert(myArray.length); // 4
本文地址:http://javascript.askforanswer.com/ruhezaijavascriptzhongchushihuashuzudechangdu.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!