创建零填充JavaScript数组的最有效方法?

dil*_*dil 552 javascript arrays

在JavaScript中创建任意长度零填充数组的最有效方法是什么?

Ori*_*iol 485

ES6介绍Array.prototype.fill.它可以像这样使用:

new Array(len).fill(0);
Run Code Online (Sandbox Code Playgroud)

不确定它是否很快,但我喜欢它,因为它简短而且自我描述.

它仍然不在IE中(检查兼容性),但有一个polyfill可用.

  • 填充速度很快.`new Array(len)`非常缓慢.`(arr = []).length = len; arr.fill(0);`是关于我见过的最快的解决方案......或者至少是捆绑的 (9认同)
  • @PimpTrizkit`arr = Array(n)`和`(arr = []).length = n`根据规范表现相同.在某些实现中,一个可能更快,但我认为没有太大的区别. (6认同)
  • 当数组变得非常大时,我看到 `fill()` 比 for 循环慢很多:https://jsperf.com/zero-filling-large-arrays 并且 `new Array(n )` 和 `a = []; a.length = n` (4认同)
  • ...我会承认我错过了这部分...当我在测试中添加第二行时...`arr.fill(0)`...所有的变化都有所改变.现在,使用`new Array()`在大多数情况下更快,除非你得到阵列大小> 100000 ...然后你可以开始再次看到速度增加.但是如果你实际上不需要用零预填充它并且可以使用标准的空阵列falisy.那么`(arr = []).length = x`在我的测试用例中大部分时间都是疯狂的. (3认同)
  • 请注意,要迭代数组(例如map或forEach),必须设置值**,否则它将跳过这些索引.您设置的值可以是您想要的任何值 - 甚至是未定义的.示例:尝试`new Array(5).forEach(val => console.log('hi'));`vs`new Array(5).fill(undefined).forEach(val => console.log('hi "));`. (3认同)
  • 好吧,我开始用多维数组测试它,它似乎大大加快了我的测试用例。刚刚在 FF41 和 Chrome45.0.2454.99 m 上做了一些更多的测试。是的,我想我真的需要更多的空间来解释自己。我承认我的大部分测试都是偏见。但是,看看这个。预定义一个 var 并仅使用这一行 `(arr = []).length = 1000;` 对 `arr = new Array(1000);` 在 Chrome 和 FF 中进行速度测试...... `new` 非常慢. 现在,对于更小的数组长度.. 说 < 50 或大约......然后`new Array()` 似乎表现更好。但.. (2认同)

zer*_*osh 377

虽然这是一个老线程,但我想加2美分.不确定这是多么缓慢/快速,但它是一个快速的单线.这是我做的:

如果我想预先填写一个数字:

Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]
Run Code Online (Sandbox Code Playgroud)

如果我想预先填写字符串:

Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]
Run Code Online (Sandbox Code Playgroud)

其他答案建议:

new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]
Run Code Online (Sandbox Code Playgroud)

但如果你想要0(数字)而不是"0"(字符串内为零),你可以这样做:

new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]
Run Code Online (Sandbox Code Playgroud)

  • (顺便说一句,我们真的不需要`new`)当你执行`Array(5)`时,你创建的对象看起来像这样:`{length:5,__ proto ___:Array.prototype}` - 试试`console.dir(Array(5))`.请注意,它没有任何属性`0`,`1`,`2`等.但是当你``apply`到`Array`构造函数时,它就像是在说'Array(undefined,undefined,undefined,undefined) ,undefined)`.你得到一个有点像`{length:5,0:undefined,1:undefined ......}`的对象.`map`适用于属性`0`,`1`等,这就是为什么你的例子不起作用的原因,但是当你使用`apply`时它就可以了. (36认同)
  • 很棒的答案!你可以用`Array.apply(null,new Array(5))解释这个技巧.map(...)`?因为简单地做(新的Array(5)).map(...)将不会像规范告诉的那样工作 (6认同)
  • 绩效基准:http://jsperf.com/zero-filled-array-creation/17 (5认同)
  • `.apply`的第一个参数实际上就是你想要的`this`.出于这些目的,`this`并不重要 - 我们只关心`.apply`的参数传播"功能" - 所以它可以是任何值.我喜欢`null`,因为它很便宜,你可能不想使用`{}`或`[]`,因为你无缘无故地实例化一个对象. (4认同)
  • 同样使用size + assign初始化比推送快得多.请参阅测试用例http://jsperf.com/zero-fill-2d-array (2认同)
  • 那么Array.apply(null,Array(5)).map(x => 0)?它有点短! (2认同)

Luc*_*iva 85

用预先计算的值填充数组的优雅方法

这是另一种使用ES6的方法,到目前为止还没有人提到过:

> Array.from(Array(3), () => 0)
< [0, 0, 0]
Run Code Online (Sandbox Code Playgroud)

它通过传递map函数作为第二个参数来工作Array.from.

在上面的示例中,第一个参数分配一个由3个位置填充的数组,undefined然后lambda函数将每个位置映射到该值0.

虽然Array(len).fill(0)较短,但是如果你需要先通过一些计算来填充数组(我知道这个问题没有要求它,但是很多人最终在这里寻找这个),它不起作用.

例如,如果您需要一个包含10个随机数的数组:

> Array.from(Array(10), () => Math.floor(10 * Math.random()))
< [3, 6, 8, 1, 9, 3, 0, 6, 7, 1]
Run Code Online (Sandbox Code Playgroud)

它比同等的更简洁(和优雅):

const numbers = Array(10);
for (let i = 0; i < numbers.length; i++) {
    numbers[i] = Math.round(10 * Math.random());
}
Run Code Online (Sandbox Code Playgroud)

此方法还可以通过利用回调中提供的索引参数来生成数字序列:

> Array.from(Array(10), (d, i) => i)
< [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)

额外答案:使用String填充数组 repeat()

由于这个答案得到了很多关注,我也想展示这个很酷的技巧.虽然没有我主要答案那么有用,但是会介绍一些尚不为人知的但非常有用的String repeat()方法.这是诀窍:

> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
Run Code Online (Sandbox Code Playgroud)

很酷,对吧?repeat()是一个非常有用的方法来创建一个字符串,重复原始字符串一定次数.之后,split()为我们创建一个数组,然后map()根据我们想要的值创建数组.按步骤分解:

> "?".repeat(10)
< "??????????"

> "?".repeat(10).split("")
< ["?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]

> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
Run Code Online (Sandbox Code Playgroud)

  • 尽管在生产中绝对不需要“repeat”技巧,但“Array.from()”完全没问题:-) (2认同)
  • ^ 为了向未来的读者澄清:上述评论暗示“Array(N)”预分配了 N 个单元格,这不一定是真的,否则“Array(2**32 - 1)”将分配比我所有的单元格更多的值。内存。浏览器引擎可能使用各种启发式方法来确定是否提前分配或使用稀疏数组。在任何情况下,您都可以使用 Array.from({ length: N }, callback) 代替。 (2认同)

Ger*_*ncy 63

已经提到的ES 6填充方法很好地处理了这个问题.大多数现代桌面浏览器已经支持目前所需的阵列原型方法(Chromium,FF,Edge和Safari)[ 1 ].您可以在MDN上查找详细信息.一个简单的用法示例是

a = new Array(10).fill(0);
Run Code Online (Sandbox Code Playgroud)

鉴于当前的浏览器支持,除非您确定您的受众使用现代桌面浏览器,否则您应该谨慎使用它.

  • 如果您填写引用类型,它将是所有引用类型的相同引用.new Array(10).fill(null).map(()=> [])将是一种简洁的解决方法(最初烧我)哈哈 (3认同)
  • ***更新2016***:此方法将所有其他内容从水中吹出,点击此处获取基准:https://jsfiddle.net/basickarl/md5z0Lqq/ (3认同)
  • @AndrewAnthonyGerst Terser:`a = Array(10).fill(0).map(_ =&gt; []);` (2认同)

Kam*_*ski 57

最短

Array(n).fill(0)

(16个字符),其中n是数组的大小


2018.10.28我从其他答案中对15个命题进行了性能比较.测试在三台浏览器上的Mac OS X 10.13.6 High Sierra上完成:Chrome 69.0.3497,Safari 12.0(13606.2.11)和Firefox 63.0(64位).

结果为n = 100000

下面我显示最快的浏览器(safari)的结果:

在此输入图像描述 在此输入图像描述

对于所有浏览器,最快的解决方案是M - 但它不是"典型阵列"(但非常快) - Safari 33.8k操作/秒,Chrome 5.2k,FF 3.5k,

典型阵列的最快解决方案:

  • Safari 5.5k和Chrome 1.1k的AB(类似)(在Firefox A 0.1k ,B 0.06k)
  • 适用于Firefox 0.6k的F(在Safari 3.1k上,Chrome 1.1k)
  • 对于Chrome和Safari A,B,F的结果很接近

最慢的解决方案:

  • G为Safari 0.02k和Firefox 0.04k(在Chrome 0.1k上)
  • D为Chrome 0.04k(在Safari 0.33k上,在Firefox 0.15k上)

解决方案N仅适用于Firefox和Chrome.

结果为n = 10

最快的:

  • M在Chrome 17.3M和Safari 13.3M(Firefox 4.7M)上最快
  • 在Firefox 16.9M(Chrome 15.6M,Safari 3.5M)上,A,B类似且速度最快

最慢的:

  • O for Safari 0.35M
  • K为Chrome 0.35M
  • N for Firefox 0.31M

结论

  • 所有浏览器上最快的解决方案(除了小型nFirefox)都是M let a = new Float32Array(n)(但不是典型的阵列) - 因为它最快的浏览器是Safari(n比Chrome 大6倍,比firefox快9倍)
  • 对于典型阵列,首选解决方案是A let a = Array(n).fill(0)(快速和短代码)

您可以在此处对您的机器进行测试.

  • 不错的测量。分析:G 很慢,因为每次迭代都会调整数组大小,而调整大小意味着进行新的内存分配。A、B、M 速度很快,因为尺寸调整只需完成一次。+1 (4认同)
  • 在 Safari 中,`for-loop` (N) 只比 `.fill` (C) 快 1.835 倍,有趣的是,当我现在运行它时,6 个月后,差异已经下降到只有 1.456 倍。因此对于 Safari 来说,最快的解决方案(N)仅比最短、最简单的版本快 45%。寓意:坚持使用最短和最简单的版本(对于大多数情况,如果不是全部情况)。它可以更快地读取、更易于维护,从而节省了开发人员昂贵的时间,而且随着时间和 CPU 速度的提高,它的回报也越来越大,而无需额外的维护。 (3认同)
  • @Roland我认为你的意思是N而不是M? (2认同)

T.J*_*der 51

注释于2013年8月更新,2015年2月更新:2009年的答案与JavaScript的泛型Array类型有关.它与ES2015中定义的新类型数组无关[现在在许多浏览器中都可用],Int32Array等等.另请注意,ES2015 fill阵列类型化数组添加了一种方法,这可能是填充它们的最有效方法......

此外,它可以为您创建阵列的一些实现带来很大的不同.特别是Chrome的V8引擎,如果认为可以使用高效,连续的内存阵列,只在必要时转移到基于对象的阵列.


对于大多数语言,它将是预分配,然后是零填充,如下所示:

function newFilledArray(len, val) {
    var rv = new Array(len);
    while (--len >= 0) {
        rv[len] = val;
    }
    return rv;
}
Run Code Online (Sandbox Code Playgroud)

但是,JavaScript数组不是真正的数组,它们就像所有其他JavaScript对象一样是键/值映射,所以没有"预分配"要做(设置长度不分配那么多的插槽来填充),也没有是否有任何理由相信,当实现可能已经优化了它们对键的处理时,通过以相反的顺序添加键,不会超过倒数到零的好处(这只是为了使循环中的比较快速)与理论上的数组有关,你通常会按顺序执行它们.

实际上,Matthew Crumley指出,Firefox上的倒计时明显慢于计数,这是我可以确认的结果 - 它是数组的一部分(循环到零仍然比循环到var的极限更快).显然,以相反的顺序将元素添加到数组是Firefox的慢速操作.实际上,JavaScript实现的结果差别很大(这并不奇怪).这是一个快速而肮脏的测试页面(下面),用于浏览器实现(非常脏,在测试期间不会产生,因此提供最少的反馈并且将与脚本时间限制相冲突).我建议在测试之间刷新; 如果不这样做,FF(至少)会在重复测试时减慢速度.

使用Array#concat的相当复杂的版本比FF上的直接init更快,因为介于1,000和2,000个元素阵列之间.不过,在Chrome的V8引擎上,每次直接初始化胜出...

这是测试页面(实时复制):

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Zero Init Test Page</title>
<style type='text/css'>
body {
    font-family:    sans-serif;
}
#log p {
    margin:     0;
    padding:    0;
}
.error {
    color:      red;
}
.winner {
    color:      green;
    font-weight:    bold;
}
</style>
<script type='text/javascript' src='prototype-1.6.0.3.js'></script>
<script type='text/javascript'>
var testdefs = {
    'downpre':  {
        total:  0,
        desc:   "Count down, pre-decrement",
        func:   makeWithCountDownPre
    },
    'downpost': {
        total:  0,
        desc:   "Count down, post-decrement",
        func:   makeWithCountDownPost
    },
    'up':       {
        total:  0,
        desc:   "Count up (normal)",
        func:   makeWithCountUp
    },
    'downandup':  {
        total:  0,
        desc:   "Count down (for loop) and up (for filling)",
        func:   makeWithCountDownArrayUp
    },
    'concat':   {
        total:  0,
        desc:   "Concat",
        func:   makeWithConcat
    }
};

document.observe('dom:loaded', function() {
    var markup, defname;

    markup = "";
    for (defname in testdefs) {
        markup +=
            "<div><input type='checkbox' id='chk_" + defname + "' checked>" +
            "<label for='chk_" + defname + "'>" + testdefs[defname].desc + "</label></div>";
    }
    $('checkboxes').update(markup);
    $('btnTest').observe('click', btnTestClick);
});

function epoch() {
    return (new Date()).getTime();
}

function btnTestClick() {

    // Clear log
    $('log').update('Testing...');

    // Show running
    $('btnTest').disabled = true;

    // Run after a pause while the browser updates display
    btnTestClickPart2.defer();
}
function btnTestClickPart2() {

    try {
        runTests();
    }
    catch (e) {
        log("Exception: " + e);
    }

    // Re-enable the button; we don't yheidl
    $('btnTest').disabled = false;
}

function runTests() {
    var start, time, counter, length, defname, def, results, a, invalid, lowest, s;

    // Get loops and length
    s = $F('txtLoops');
    runcount = parseInt(s);
    if (isNaN(runcount) || runcount <= 0) {
        log("Invalid loops value '" + s + "'");
        return;
    }
    s = $F('txtLength');
    length = parseInt(s);
    if (isNaN(length) || length <= 0) {
        log("Invalid length value '" + s + "'");
        return;
    }

    // Clear log
    $('log').update('');

    // Do it
    for (counter = 0; counter <= runcount; ++counter) {

        for (defname in testdefs) {
            def = testdefs[defname];
            if ($('chk_' + defname).checked) {
                start = epoch();
                a = def.func(length);
                time = epoch() - start;
                if (counter == 0) {
                    // Don't count (warm up), but do check the algorithm works
                    invalid = validateResult(a, length);
                    if (invalid) {
                        log("<span class='error'>FAILURE</span> with def " + defname + ": " + invalid);
                        return;
                    }
                }
                else {
                    // Count this one
                    log("#" + counter + ": " + def.desc + ": " + time + "ms");
                    def.total += time;
                }
            }
        }
    }

    for (defname in testdefs) {
        def = testdefs[defname];
        if ($('chk_' + defname).checked) {
            def.avg = def.total / runcount;
            if (typeof lowest != 'number' || lowest > def.avg) {
                lowest = def.avg;
            }
        }
    }

    results =
        "<p>Results:" +
        "<br>Length: " + length +
        "<br>Loops: " + runcount +
        "</p>";
    for (defname in testdefs) {
        def = testdefs[defname];
        if ($('chk_' + defname).checked) {
            results += "<p" + (lowest == def.avg ? " class='winner'" : "") + ">" + def.desc + ", average time: " + def.avg + "ms</p>";
        }
    }
    results += "<hr>";
    $('log').insert({top: results});
}

function validateResult(a, length) {
    var n;

    if (a.length != length) {
        return "Length is wrong";
    }
    for (n = length - 1; n >= 0; --n) {
        if (a[n] != 0) {
            return "Index " + n + " is not zero";
        }
    }
    return undefined;
}

function makeWithCountDownPre(len) {
    var a;

    a = new Array(len);
    while (--len >= 0) {
        a[len] = 0;
    }
    return a;
}

function makeWithCountDownPost(len) {
    var a;

    a = new Array(len);
    while (len-- > 0) {
        a[len] = 0;
    }
    return a;
}

function makeWithCountUp(len) {
    var a, i;

    a = new Array(len);
    for (i = 0; i < len; ++i) {
        a[i] = 0;
    }
    return a;
}

function makeWithCountDownArrayUp(len) {
    var a, i;

    a = new Array(len);
    i = 0;
    while (--len >= 0) {
        a[i++] = 0;
    }
    return a;
}

function makeWithConcat(len) {
    var a, rem, currlen;

    if (len == 0) {
        return [];
    }
    a = [0];
    currlen = 1;
    while (currlen < len) {
        rem = len - currlen;
        if (rem < currlen) {
            a = a.concat(a.slice(0, rem));
        }
        else {
            a = a.concat(a);
        }
        currlen = a.length;
    }
    return a;
}

function log(msg) {
    $('log').appendChild(new Element('p').update(msg));
}
</script>
</head>
<body><div>
<label for='txtLength'>Length:</label><input type='text' id='txtLength' value='10000'>
<br><label for='txtLoops'>Loops:</label><input type='text' id='txtLoops' value='10'>
<div id='checkboxes'></div>
<br><input type='button' id='btnTest' value='Test'>
<hr>
<div id='log'></div>
</div></body>
</html>
Run Code Online (Sandbox Code Playgroud)


dea*_*unk 35

默认情况下Uint8Array,Uint16ArrayUint32Array阶级保持零作为它的值,所以你不需要任何复杂的充填技术,只是做:

var ary = new Uint8Array(10);
Run Code Online (Sandbox Code Playgroud)

ary默认情况下,数组的所有元素都将为零.

  • 这很好但是请注意,这不能像普通数组那样对待,例如`Array.isArray(ary)`是`false`.长度也是只读的,因此您不能像使用`ary.push`那样将新项目推送到它 (5认同)
  • @MusikAnimal,Array.from(new Uint8Array(10))将提供一个普通数组。 (2认同)

fox*_*ris 27

如果使用ES6,可以像这样使用Array.from():

Array.from({ length: 3 }, () => 0);
//[0, 0, 0]
Run Code Online (Sandbox Code Playgroud)

结果与...相同

Array.from({ length: 3 }).map(() => 0)
//[0, 0, 0]
Run Code Online (Sandbox Code Playgroud)

因为

Array.from({ length: 3 })
//[undefined, undefined, undefined]
Run Code Online (Sandbox Code Playgroud)


kan*_*gax 23

function makeArrayOf(value, length) {
  var arr = [], i = length;
  while (i--) {
    arr[i] = value;
  }
  return arr;
}

makeArrayOf(0, 5); // [0, 0, 0, 0, 0]

makeArrayOf('x', 3); // ['x', 'x', 'x']
Run Code Online (Sandbox Code Playgroud)

请注意,while通常比更有效for-in,forEach等等.

  • 是不是`i`局部变量无关?`length`是按值传递的,所以你应该能够直接递减它. (3认同)
  • 虽然这首先看起来很棒,但不幸的是,在一个任意点(例如`arr [i] = value`)中分配值非常慢.从头到尾循环并使用`arr.push(value)`要快得多.这很烦人,因为我更喜欢你的方法. (3认同)
  • 当然.我只为会议/清晰度添加了"i". (2认同)

Mat*_*ley 20

我已经在IE 6/7/8,Firefox 3.5,Chrome和Opera中测试了预分配/非预分配,向上/向下计数和for/while循环的所有组合.

以下功能在Firefox,Chrome和IE8中始终是最快或非常接近的,并且比Opera和IE 6中最快的速度慢得多.在我看来,它也是最简单和最清晰的.我找到了几个浏览器,其中while循环版本稍微快一些,所以我也将它包含在内以供参考.

function newFilledArray(length, val) {
    var array = [];
    for (var i = 0; i < length; i++) {
        array[i] = val;
    }
    return array;
}
Run Code Online (Sandbox Code Playgroud)

要么

function newFilledArray(length, val) {
    var array = [];
    var i = 0;
    while (i < length) {
        array[i++] = val;
    }
    return array;
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,您还可以将 var array = [] 声明放入 for 循环的第一部分,仅用逗号分隔。 (2认同)

All*_*ice 18

使用对象表示法

var x = [];
Run Code Online (Sandbox Code Playgroud)

零填充?喜欢...

var x = [0,0,0,0,0,0];
Run Code Online (Sandbox Code Playgroud)

充满'未定义'......

var x = new Array(7);
Run Code Online (Sandbox Code Playgroud)

使用零的obj表示法

var x = [];
for (var i = 0; i < 10; i++) x[i] = 0;
Run Code Online (Sandbox Code Playgroud)

作为旁注,如果你修改了Array的原型,两者都是

var x = new Array();
Run Code Online (Sandbox Code Playgroud)

var y = [];
Run Code Online (Sandbox Code Playgroud)

将有那些原型修改

无论如何,我不会过分关注这个操作的效率或速度,你可能会做的很多其他事情比实现包含零的任意长度数组更浪费和更昂贵.

  • 呃...这个数组中没有`null`s - `var x = new Array(7);` (5认同)
  • 实际上,数组没有填充任何新的Array(n),甚至没有'undefined',它只是将数组长度值设置为n.你可以通过调用(new Array(1)).forEach(...)来检查这个.forEach永远不会执行,不像你在[undefined]上调用它. (5认同)
  • `new Array(7)`确实**不会**创建​​一个"填充未定义"的数组.它创建一个长度为7的**空**数组. (4认同)
  • 您可能想重新考虑部分答案,因为@RobG 所说的很关键(如果您所说的是真的,映射会容易得多) (2认同)

аle*_*kyі 15

const arr = Array.from({ length: 10 }).fill(0);
console.log(arr)
Run Code Online (Sandbox Code Playgroud)


Eli*_*Eli 14

function zeroFilledArray(size) {
    return new Array(size + 1).join('0').split('');
}
Run Code Online (Sandbox Code Playgroud)

  • @Yuval或者只是`new array(size + 1).join('0').split('').map(Number)` (6认同)
  • 您也可以使用`new Array(size + 1).join("x").split("x").map(function(){return 0;})`来获取实际数字 (3认同)

Nen*_*vic 13

如果您需要的代码,我发现实现这一目标是创建一个零阵的最快方法的执行过程中创建不同长度的许多零个填充阵列一次,使用的关于这一主题提到的方法之一,长度的您知道永远不会超过它,然后根据需要切片该数组.

例如(使用上面选择的答案中的函数初始化数组),创建一个长度为maxLength的零填充数组,作为需要零数组的代码可见的变量:

var zero = newFilledArray(maxLength, 0);
Run Code Online (Sandbox Code Playgroud)

现在,每次切片这个数组,你需要长度的零满阵requiredLength < 最大长度:

zero.slice(0, requiredLength);
Run Code Online (Sandbox Code Playgroud)

我在执行代码期间数千次创建零填充数组,这极大地加速了这个过程.


Sal*_*ali 11

我没有反对:

Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
new Array(5+1).join('0').split('').map(parseFloat);
Run Code Online (Sandbox Code Playgroud)

由Zertosh建议,但在新的ES6阵列扩展允许您使用fill方法本地执行此操作.现在IE边缘,Chrome和FF支持它,但检查兼容性表

new Array(3).fill(0)会给你的[0, 0, 0].您可以使用任何值填充数组new Array(5).fill('abc')(甚至是对象和其他数组).

最重要的是,您可以使用fill修改以前的数组:

arr = [1, 2, 3, 4, 5, 6]
arr.fill(9, 3, 5)  # what to fill, start, end
Run Code Online (Sandbox Code Playgroud)

这给你: [1, 2, 3, 9, 9, 6]


dur*_*rum 10

我通常这样做的方式(并且速度惊人)正在使用Uint8Array.例如,创建1M元素的零填充向量:

  var zeroFilled = [].slice.apply(new Uint8Array(1000000))
Run Code Online (Sandbox Code Playgroud)

我是Linux用户并且一直为我工作,但是一旦使用Mac的朋友有一些非零元素.我以为他的机器出现故障,但仍然是我们发现修复它的最安全的方法:

  var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000)) 
Run Code Online (Sandbox Code Playgroud)

编辑

Chrome 25.0.1364.160

  1. Frederik Gottlieb - 6.43
  2. Sam Barnum - 4.83
  3. 伊莱 - 3.68
  4. 约书亚2.91
  5. Mathew Crumley - 2.67
  6. bduran - 2.55
  7. 艾伦·赖斯 - 2.11
  8. kangax - 0.68
  9. TJ.克劳德 - 0.67
  10. 泽托什 - 错误

Firefox 20.0

  1. 艾伦·赖斯 - 1.85
  2. 约书亚 - 1.82
  3. Mathew Crumley - 1.79
  4. bduran - 1.37
  5. Frederik Gottlieb - 0.67
  6. Sam Barnum - 0.63
  7. 伊莱 - 0.59
  8. kagax - 0.13
  9. TJ.克劳德 - 0.13
  10. 泽托什 - 错误

缺少最重要的测试(至少对我而言):Node.js测试.我怀疑它接近Chrome基准测试.


Vic*_*Vic 9

ES6解决方案:

[...new Array(5)].map(x => 0); // [0, 0, 0, 0, 0]
Run Code Online (Sandbox Code Playgroud)


Isa*_*c B 8

ECMAScript2016开始,大型阵列有一个明显的选择.

由于这个答案仍然显示在谷歌搜索的顶部附近,这里是2017年的答案.

这是一个当前的jsbench,有几十种流行的方法,包括到目前为止在这个问题上提出的很多方法.如果您找到更好的方法,请添加,分叉和共享.

我想指出,没有真正最有效的方法来创建任意长度的零填充数组.您可以针对速度进行优化,或者为了清晰度和可维护性 - 根据项目的需要,可以将其视为更有效的选择.

在优化速度时,您需要:使用文字语法创建数组; 设置长度,初始化迭代变量,并使用while循环遍历数组.这是一个例子.

const arr = [];
arr.length = 120000;
let i = 0;
while (i < 120000) {
  arr[i] = 0;
  i++;
}
Run Code Online (Sandbox Code Playgroud)

另一种可能的实现方式是:

(arr = []).length = n;
let i = 0;
while (i < n) {
    arr[i] = 0;
    i++;
}
Run Code Online (Sandbox Code Playgroud)

但我强烈反对在实践中使用第二次植入,因为它不太清楚,并且不允许你在数组变量上保持块范围.

这些比填充for循环快得多,比标准方法快约90%

const arr = Array(n).fill(0);
Run Code Online (Sandbox Code Playgroud)

但是这种填充方法仍然是小型阵列最有效的选择,因为它具有清晰,简洁和可维护性.性能差异可能不会杀死你,除非你制作了大量数千或更多的数组.

其他一些重要的说明.var在使用ES6或更高版本时,大多数样式指南建议您在没有特殊原因的情况下不再使用.使用const该不会被重新定义变量,let变量即会.该MDNAirbnb的风格指南是伟大的地方去的最佳实践的详细信息.这些问题不是关于语法的问题,但重要的是,在搜索新旧答案时,新手JS的人员应该了解这些新标准.


dje*_*lin 7

使用lodash下划线

_.range(0, length - 1, 0);
Run Code Online (Sandbox Code Playgroud)

或者,如果您有一个数组存在,并且您想要一个长度相同的数组

array.map(_.constant(0));
Run Code Online (Sandbox Code Playgroud)


Jua*_*dez 7

创建一个全新的阵列

new Array(arrayLength).fill(0);
Run Code Online (Sandbox Code Playgroud)

在现有数组的末尾添加一些值

[...existingArray, ...new Array(numberOfElementsToAdd).fill(0)]

new Array(arrayLength).fill(0);
Run Code Online (Sandbox Code Playgroud)


Cor*_*ter 5

怎么样new Array(51).join('0').split('')


Eug*_*rin 5

没有在答案中看到这种方法,所以这里是:

"0".repeat( 200 ).split("").map( parseFloat )
Run Code Online (Sandbox Code Playgroud)

结果你将获得长度为200的零值数组:

[ 0, 0, 0, 0, ... 0 ]
Run Code Online (Sandbox Code Playgroud)

我不确定这段代码的性能,但如果你将它用于相对较小的数组,它应该不是问题.

  • 无论是最快还是最短,都是对解决方案多样性的有益贡献. (4认同)