首页 文章

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

提问于
浏览
372

我在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's explanation of its behavior阅读后,看起来jsLint并不喜欢 new Array() 语法,而是在声明数组时更喜欢 [] .

所以我有几个问题 . 首先,为什么?我是否因使用 new Array() 语法而冒任何风险?是否存在我应该注意的浏览器不兼容性?第二,如果我切换到方括号语法,有没有办法声明一个数组并在一行上设置它的长度,或者我必须做这样的事情:

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

16 回答

  • 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 } 对象值展开为其参数 .

  • 5
    var arr=[];
    arr[5]=0;
    alert("length="+arr.length); // gives 6
    
  • 150

    我很惊讶没有建议的功能解决方案允许您在一行中设置长度 . 以下是基于UnderscoreJS:

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

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

  • 23

    使用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) 简洁得多

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

  • 293
    [...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 创建 2D 数组时应创建新实例 . 但实际发生的是同一个数组将被存储为参考 .

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

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

    所以它会

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

    此代码演示了您不应使用 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
    
  • 3

    ES6引入了Array.from,它允许您从任何 "array-like"iterables 对象创建 Array

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

    在这种情况下, {length: 10} 表示 "array-like" 对象的最小定义:仅定义了 length 属性的空对象 .

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

  • 20

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

    var x = [,,,,];
    
  • 7

    最短的:

    [...Array(1000)]
    
  • 15

    (作为评论,这可能更好,但是太长了)

    因此,在阅读本文之后,我很好奇预分配实际上是否更快,因为理论上它应该是 . 但是,这个博客提供了一些建议反对它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
    
  • 39
    • 为什么要初始化长度?从理论上讲,没有必要这样做 . 它甚至可能导致令人困惑的行为,因为所有使用 length 来查明数组是否为空的测试都会报告该数组不为空 .
      Some tests表明如果之后填充数组,设置大型数组的初始长度会更有效,但性能增益(如果有的话)似乎因浏览器而异 .

    • jsLint不喜欢 new Array() 因为构造函数不明确 .

    new Array(4);
    

    创建一个空数组 of length 4.但是

    new Array('4');
    

    创建一个数组 containing the value '4' .

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

    var data = [];
    var length = 5; // user defined length
    
    for(var i = 0; i < length; i++) {
        data.push(createSomeObject());
    }
    
  • 20

    数组构造函数有一个ambiguous syntax,而JSLint毕竟只会伤害你的感情 .

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

    至于你的选择, array.length 是唯一的"clean" . 问题是,为什么你需要首先设置尺寸?尝试重构您的代码以摆脱这种依赖 .

  • -2

    请人们不要放弃你的旧习惯 . 分配内存一次然后使用该数组中的条目(从旧)开始,并且随着数组的增长分配多次(这不可避免地是系统在其他建议的方法下做的事情)之间的速度差异很大 .

    当然,这些都不重要,直到你想用更大的数组做一些很酷的事情 . 然后呢 .

    看来目前在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左右,大约50毫秒,n = 1000000,花了大约5秒),和

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

    超过一分钟(相同的镀铬控制台上的10000大约90秒,或慢大约2000倍) . 这不仅仅是分配,还有10000次推送,for循环等 .

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

  • 370

    如上所述,使用 new Array(size) 有点危险 . 而不是直接使用它,将其放在"array creator function"内 . 您可以轻松确保此功能没有错误,并避免直接调用 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;
    }
    

相关问题