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

创建零填充JavaScript数组的最有效方法是什么?,javascript,arrays,Javascript,Arrays,在JavaScript中创建任意长度的零填充数组最有效的方法是什么?使用对象表示法 var x = []; 零填充?像 var x = [0,0,0,0,0,0]; 填充了“未定义” var x = new Array(7); 带零的obj表示法 var x = []; for (var i = 0; i < 10; i++) x[i] = 0; 及 将有这些原型的修改 无论如何,我不会过分担心此操作的效率或速度,您可能会做很多其他事情,这些事情比实例化包含零的任意长度数组更浪费和

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

使用对象表示法

var x = [];
零填充?像

var x = [0,0,0,0,0,0];
填充了“未定义”

var x = new Array(7);
带零的obj表示法

var x = [];
for (var i = 0; i < 10; i++) x[i] = 0;

将有这些原型的修改

无论如何,我不会过分担心此操作的效率或速度,您可能会做很多其他事情,这些事情比实例化包含零的任意长度数组更浪费和昂贵

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']
请注意,
而对于in
forEach
等,
通常比
更有效。

注意:2013年8月添加,2015年2月更新:以下答案与JavaScript的通用
数组类型有关。它与ES2015中定义的较新的类型的数组(现在在许多浏览器中都可以使用)无关,比如
Int32Array
等等。还请注意,ES2015在和中添加了一个
fill
方法,这可能是填充它们的最有效方法

此外,它还可以对一些实现产生很大的影响,比如如何创建阵列。特别是Chrome的V8引擎,如果认为可以的话,它会尝试使用一个高效、连续的内存阵列,只有在必要时才会转向基于对象的阵列


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

function newFilledArray(len, val) {
    var rv = new Array(len);
    while (--len >= 0) {
        rv[len] = val;
    }
    return rv;
}
new Array(len).fill(0);
Array.from({ length: 3 }, () => 0);
//[0, 0, 0]
但是,JavaScript数组,它们是键/值映射,就像所有其他JavaScript对象一样,因此没有“预分配”要做(设置长度不会分配那么多要填充的插槽),也没有任何理由相信倒计时到零的好处(这只是为了快速在循环中进行比较)当实现可能已经优化了它们对与数组相关的键的处理时,按相反的顺序添加键并不会抵消这一点,因为在理论上,您通常会按顺序进行操作

事实上,Matthew Crumley指出,Firefox上的倒计时明显比倒计时慢,这是我可以确认的结果——这是它的数组部分(在一个变量中,倒计时到零比倒计时到一个极限还要快)。显然,在Firefox上以相反的顺序向数组中添加元素是一个缓慢的操作。事实上,JavaScript实现的结果差别很大(这并不奇怪)。下面是一个针对浏览器实现的快速而肮脏的测试页面(非常肮脏,在测试过程中不会屈服,因此提供的反馈最少,并且会违反脚本时间限制)。我建议在测试之间刷新;如果您不这样做,FF(至少)在重复测试中会减慢速度

使用Array#concat的相当复杂的版本比FF上的直接init快,大约在1000到2000个元素数组之间。不过,在Chrome的V8引擎上,straight init每次都会胜出

这是测试页面():


零初始测试页
身体{
字体系列:无衬线;
}
#对数p{
保证金:0;
填充:0;
}
.错误{
颜色:红色;
}
.获胜者{
颜色:绿色;
字体大小:粗体;
}
var testdefs={
“downpre”:{
总数:0,
描述:“倒计时,预减量”,
func:makeWithCountDownPre
},
“直柱”:{
总数:0,
描述:“倒计时,后减量”,
func:makeWithCountDownPost
},
“向上”:{
总数:0,
描述:“向上计数(正常)”,
func:makeWithCountUp
},
“向下和向上”:{
总数:0,
描述:“倒计时(用于循环)和向上计数(用于填充)”,
func:makeWithCountDownArrayUp
},
“康卡特”:{
总数:0,
描述:“海螺”,
func:makeWithConcat
}
};
document.observe('dom:loaded',function()){
var标记,defname;
加价=”;
for(testdefs中的defname){
加价+=
"" +
“+testdefs[defname].desc+”;
}
$(“复选框”)。更新(标记);
$('btnTest')。观察('click',btnTest click);
});
函数(){
return(新日期()).getTime();
}
函数btnTestClick(){
//清除日志
$('log')。更新('Testing…');
//秀跑
$('btnTest')。disabled=true;
//在浏览器更新显示时暂停运行
btnTestClickPart2.defer();
}
函数btnTestClickPart2(){
试一试{
运行测试();
}
捕获(e){
日志(“异常:+e);
}
//重新启用按钮;我们不需要
$('btnTest')。禁用=false;
}
函数runTests(){
变量开始、时间、计数器、长度、定义名称、定义、结果、a、无效、最低、s;
//获取循环和长度
s=$F('txtLoops');
runcount=parseInt(s);

如果(isNaN(runcount)| | runcount我知道我在某处有这个原型:)

编辑:测试

作为对Joshua和其他方法的回应,我运行了自己的基准测试,我看到的结果与报道的完全不同

以下是我测试的内容:

//my original method
Array.prototype.init = function(x,n)
{
    if(typeof(n)=='undefined') { n = this.length; }
    while (n--) { this[n] = x; }
    return this;
}

//now using push which I had previously thought to be slower than direct assignment
Array.prototype.init2 = function(x,n)
{
    if(typeof(n)=='undefined') { n = this.length; }
    while (n--) { this.push(x); }
    return this;
}

//joshua's method
function newFilledArray(len, val) {
    var a = [];
    while(len--){
        a.push(val);
    }
    return a;
}

//test m1 and m2 with short arrays many times 10K * 10

var a = new Date();
for(var i=0; i<10000; i++)
{
    var t1 = [].init(0,10);
}
var A = new Date();

var b = new Date();
for(var i=0; i<10000; i++)
{
    var t2 = [].init2(0,10);
}
var B = new Date();

//test m1 and m2 with long array created once 100K

var c = new Date();
var t3 = [].init(0,100000);
var C = new Date();

var d = new Date();
var t4 = [].init2(0,100000);
var D = new Date();

//test m3 with short array many times 10K * 10

var e = new Date();
for(var i=0; i<10000; i++)
{
    var t5 = newFilledArray(10,0);
}
var E = new Date();

//test m3 with long array created once 100K

var f = new Date();
var t6 = newFilledArray(100000, 0)
var F = new Date();

因此,据我估计,推送确实总体上较慢,但在FF中使用较长的阵列时性能更好,但在IE中性能更差,这在总体上很糟糕(平息惊讶)。

我测试了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;
}
函数newFilledArray(长度,val){
var数组=[];
对于(变量i=0;i

函数newFilledArray(长度,val){
var数组=[];
var i=0;
while(i//my original method
Array.prototype.init = function(x,n)
{
    if(typeof(n)=='undefined') { n = this.length; }
    while (n--) { this[n] = x; }
    return this;
}

//now using push which I had previously thought to be slower than direct assignment
Array.prototype.init2 = function(x,n)
{
    if(typeof(n)=='undefined') { n = this.length; }
    while (n--) { this.push(x); }
    return this;
}

//joshua's method
function newFilledArray(len, val) {
    var a = [];
    while(len--){
        a.push(val);
    }
    return a;
}

//test m1 and m2 with short arrays many times 10K * 10

var a = new Date();
for(var i=0; i<10000; i++)
{
    var t1 = [].init(0,10);
}
var A = new Date();

var b = new Date();
for(var i=0; i<10000; i++)
{
    var t2 = [].init2(0,10);
}
var B = new Date();

//test m1 and m2 with long array created once 100K

var c = new Date();
var t3 = [].init(0,100000);
var C = new Date();

var d = new Date();
var t4 = [].init2(0,100000);
var D = new Date();

//test m3 with short array many times 10K * 10

var e = new Date();
for(var i=0; i<10000; i++)
{
    var t5 = newFilledArray(10,0);
}
var E = new Date();

//test m3 with long array created once 100K

var f = new Date();
var t6 = newFilledArray(100000, 0)
var F = new Date();
IE7 deltas:
dA=156
dB=359
dC=125
dD=375
dE=468
dF=412

FF3.5 deltas:
dA=6
dB=13
dC=63
dD=8
dE=12
dF=8
function newFilledArray(length, val) {
    var array = [];
    for (var i = 0; i < length; i++) {
        array[i] = val;
    }
    return array;
}
function newFilledArray(length, val) {
    var array = [];
    var i = 0;
    while (i < length) {
        array[i++] = val;
    }
    return array;
}
function newFilledArray(len, val) {
    var a = [];
    while(len--){
        a.push(val);
    }
    return a;
}

var st = (new Date()).getTime();
newFilledArray(1000000, 0)
console.log((new Date()).getTime() - st); // returned 63, 65, 62 milliseconds
var a = [];
var len = 1000000;
var st = (new Date()).getTime();
while(len){
    a.push(0);
    len -= 1;
}
console.log((new Date()).getTime() - st); // returned 863, 894, 875 milliseconds
st = (new Date()).getTime();
len = 1000000;
a = [];
for(var i = 0; i < len; i++){
    a.push(0);
}
console.log((new Date()).getTime() - st); // returned 1155, 1179, 1163 milliseconds
var zero = newFilledArray(maxLength, 0);
zero.slice(0, requiredLength);
function zeroFilledArray(size) {
    return new Array(size + 1).join('0').split('');
}
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]
Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]
new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]
new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]
function filledArray(len, value) {
    if (len <= 0) return [];
    var result = [value];
    while (result.length < len/2) {
        result = result.concat(result);
    }
    return result.concat(result.slice(0, len-result.length));
}
function filledArrayString(len, value) {
    return new Array(len+1).join(value).split('');
}
function makeRec(len, acc) {
    if (acc == null) acc = [];
    if (len <= 1) return acc;
    var b = makeRec(len >> 1, [0]);
    b = b.concat(b);
    if (len & 1) b = b.concat([0]);
    return b;
},
  var zeroFilled = [].slice.apply(new Uint8Array(1000000))
  var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000)) 
var ary = new Uint8Array(10);
_.range(0, length - 1, 0);
array.map(_.constant(0));
new Array(len).fill(0);
if (!Array.prototype.fill) {
  Array.prototype.fill = function(value) {

    // Steps 1-2.
    if (this == null) {
      throw new TypeError('this is null or not defined');
    }

    var O = Object(this);

    // Steps 3-5.
    var len = O.length >>> 0;

    // Steps 6-7.
    var start = arguments[1];
    var relativeStart = start >> 0;

    // Step 8.
    var k = relativeStart < 0 ?
      Math.max(len + relativeStart, 0) :
      Math.min(relativeStart, len);

    // Steps 9-10.
    var end = arguments[2];
    var relativeEnd = end === undefined ?
      len : end >> 0;

    // Step 11.
    var final = relativeEnd < 0 ?
      Math.max(len + relativeEnd, 0) :
      Math.min(relativeEnd, len);

    // Step 12.
    while (k < final) {
      O[k] = value;
      k++;
    }

    // Step 13.
    return O;
  };
}
(function(n) { while(n-- && this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]
(function(n) { for(;n--;this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]
function fill(size, content) {
  for(;size--;this.push(content));
  return this;
}
var helloArray = fill.call([], 5, 'hello');
// => ['hello', 'hello', 'hello', 'hello', 'hello']
var helloWorldArray = fill.call(helloArray, 5, 'world');
// => ['hello', 'hello', 'hello', 'hello', 'hello', 'world', 'world', 'world', 'world', 'world']
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
new Array(5+1).join('0').split('').map(parseFloat);
arr = [1, 2, 3, 4, 5, 6]
arr.fill(9, 3, 5)  # what to fill, start, end
a = new Array(10).fill(0);
a=i=[];for(;i<100;)a[i++]=0;

edit:
for(a=i=[];i<100;)a[i++]=0;
or
for(a=[],i=100;i--;)a[i]=0;
var a=[],i=0;for(;i<100;)a[i++]=0;

edit:
for(var i=100,a=[];i--;)a[i]=0;
> Array.from(Array(3), () => 0)
< [0, 0, 0]
> Array.from(Array(10), () => Math.floor(10 * Math.random()))
< [3, 6, 8, 1, 9, 3, 0, 6, 7, 1]
const numbers = Array(10);
for (let i = 0; i < numbers.length; i++) {
    numbers[i] = Math.round(10 * Math.random());
}
> Array.from(Array(10), (d, i) => i)
< [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
> "?".repeat(10)
< "??????????"

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

> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
Array.from({ length: 3 }, () => 0);
//[0, 0, 0]
Array.from({ length: 3 }).map(() => 0)
//[0, 0, 0]
Array.from({ length: 3 })
//[undefined, undefined, undefined]
"0".repeat( 200 ).split("").map( parseFloat )
[ 0, 0, 0, 0, ... 0 ]
[...new Array(5)].map(x => 0); // [0, 0, 0, 0, 0]
new Array(arrayLength).fill(0);