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

2020/09/23 05:41 · javascript ·  · 0评论

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

ES6引入Array.prototype.fill可以这样使用:

new Array(len).fill(0);

不知道它是否很快,但我喜欢它,因为它简短而自描述。

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

尽管这是旧线程,但我想在其中加2美分。不知道这有多慢/快,但这只是一个快速的班轮。这是我的工作:

如果我要预填数字:

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

但是如果您想要0(数字)而不是“ 0”(字符串中的零),则可以执行以下操作:

new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]

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

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

> Array.from(Array(3), () => 0)
< [0, 0, 0]

通过将map函数作为的第二个参数来工作Array.from

在上面的示例中,第一个参数分配一个由3个位置填充的数组,该位置填充了该值undefined,然后lambda函数将其中的每个映射到value 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]

它比等效的方法更加简洁(和优雅):

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

通过利用回调中提供的index参数,此方法还可用于生成数字序列:

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

奖励答案:使用字符串填充数组 repeat()

由于这个答案引起了广泛关注,因此我也想展示这个很酷的技巧。虽然不如我的主要回答有用,但将介绍仍然不是很了解,但是非常有用的String repeat()方法。这是窍门:

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

酷吧?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]

简而言之

最快的解决方案

let a = new Array(n); for (let i=0; i<n; ++i) a[i] = 0;

最短(方便)的解决方案(小型阵列慢3倍,大型阵列慢3倍(在Firefox上最慢))

Array(n).fill(0)


细节

今天,2020.06.09我在浏览器Chrome 83.0,Firefox 77.0和Safari 13.1的macOS High Sierra 10.13.6上执行测试。我测试了两个测试用例的选定解决方案

  • 小阵列-具有10个元素-您可以在此处执行测试
  • 大阵列-具有1M个元素-您可以在此处执行测试

结论

  • 基于new Array(n)+for(N)的解决方案是适用于小型阵列和大型阵列的最快解决方案(Chrome除外,但在那里仍然非常快),建议将其作为快速跨浏览器解决方案
  • 基于new Float32Array(n)(I)的解决方案返回非典型数组(例如,您无法调用push(..)它),因此我不将其结果与其他解决方案进行比较-但是,对于所有浏览器中的大型数组,该解决方案的速度比其他解决方案快10-20倍
  • 基于for(L,M,N,O)的解决方案适用于小型阵列
  • fill对于大型阵列,基于(B,C)的解决方案在Chrome和Safari上运行速度很快,但在Firefox上却最慢。对于中等大小的阵列,它们的速度中等
  • Array.apply(P)为基础的解决方案将大数组引发错误

在此处输入图片说明

代码和示例

以下代码介绍了测量中使用的解决方案

Chrome的结果范例

在此处输入图片说明

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

a = new Array(10).fill(0);

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

注意于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;
}

但是,JavaScript数组并不是真正的数组,就像所有其他JavaScript对象一样,它们是键/值映射,因此不需要“预分配”(设置长度不会分配那么多的插槽来填充),也没有有什么理由相信,当实现可能已经优化了对键的处理时,通过倒序添加键并不能抵消倒计数为零(只是使循环中的比较很快)的好处。与数组有关的理论上,您通常会按顺序进行。

实际上,马修·克鲁姆利(Matthew Crumley)指出,在Firefox上向下计数明显要比向上计数慢,我可以证实这一点-这是它的数组部分(向下循环为零仍比循环至变量上限要快)。显然,以相反的顺序将元素添加到数组是Firefox上的缓慢操作。实际上,JavaScript实现的结果差异很大(这并不奇怪)。这是一个用于浏览器实现的快速且肮脏的测试页面(如下)(非常肮脏,在测试期间不会产生,因此提供的反馈最少,并且会违反脚本时间限制)。我建议在测试之间进行刷新。如果不这样做,FF(至少)会减慢重复测试的速度。

使用Array#concat的相当复杂的版本比在FF上进行直接初始化要快,因为它在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>

默认情况下Uint8ArrayUint16ArrayUint32Array类将零作为其值,因此您不需要任何复杂的填充技术,只需执行以下操作:

var ary = new Uint8Array(10);

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

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

Array.from({ length: 3 }, () => 0);
//[0, 0, 0]

结果与

Array.from({ length: 3 }).map(() => 0)
//[0, 0, 0]

因为

Array.from({ length: 3 })
//[undefined, undefined, undefined]
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']

请注意,while通常比更有效for-inforEach等等。

使用对象符号

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;

附带说明一下,如果您修改Array的原型,

var x = new Array();

var y = [];

将进行原型修改

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

我已经测试了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;
}

要么

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

如果您需要在执行代码期间创建许多不同长度的零填充数组,我发现实现此目的的最快方法是使用本主题中提到的方法之一,一次创建一个零数组您知道永远不会超过它,然后根据需要对该数组进行切片。

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

var zero = newFilledArray(maxLength, 0);

现在,每当您需要长度为requiredLength < maxLength的零填充数组时,就对它进行切片

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);
new Array(5+1).join('0').split('').map(parseFloat);

由Zertosh提出,但是在新的ES6数组扩展中,您可以使用fill方法原生进行此操作现在IE edge,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

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

我通常使用的方法(而且速度惊人)非常快Uint8Array例如,创建一个零填充的1M元素矢量:

  var zeroFilled = [].slice.apply(new Uint8Array(1000000))

我是Linux用户,一直为我工作,但是曾经有一个使用Mac的朋友有一些非零元素。我以为他的机器出现故障,但是这仍然是我们找到的最安全的解决方法:

  var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000)) 

已编辑

铬25.0.1364.160

  1. 弗雷德里克·戈特利布-6.43
  2. 山姆·巴纳姆-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. zertosh-错误

Firefox 20.0

  1. 艾伦·赖斯-1.85
  2. 约书亚-1.82
  3. 马修·克鲁姆(Mathew Crumley)-1.79
  4. 布杜兰-1.37
  5. 弗雷德里克·戈特利布-0.67
  6. 山姆·巴纳姆-0.63
  7. 礼-0.59
  8. kagax-0.13
  9. Tj。拥挤者-0.13
  10. zertosh-错误

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

使用lodash下划线

_.range(0, length - 1, 0);

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

array.map(_.constant(0));

ES6解决方案:

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

创建一个全新的阵列

new Array(arrayLength).fill(0);

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

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

//**To create an all new Array**

console.log(new Array(5).fill(0));

//**To add some values at the end of an existing Array**

let existingArray = [1,2,3]

console.log([...existingArray, ...new Array(5).fill(0)]);

ECMAScript2016开始,大型数组有一个明确的选择。

由于此答案仍显示在Google搜索顶部附近,因此这是2017年的答案。

这是当前的jsbench,其中包含数十种流行的方法,其中包括到目前为止针对此问题提出的许多方法。如果您找到更好的方法,请添加,合并和共享。

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

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

const arr = [];
arr.length = 120000;
let i = 0;
while (i < 120000) {
  arr[i] = 0;
  i++;
}

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

(arr = []).length = n;
let i = 0;
while (i < n) {
    arr[i] = 0;
    i++;
}

但是我强烈不建议在实践中使用第二种植入方法,因为这种方法不太清楚,并且不允许您对数组变量保持块作用域。

它们比用for循环填充要快得多,并且比标准方法要快90%。

const arr = Array(n).fill(0);

但是,这种填充方法由于其清晰,简洁和可维护性,仍然是较小数组的最有效选择。除非您制作许多长度在数千或更多数量级的阵列,否则性能差异可能不会杀死您。

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

const arr = Array.from({ length: 10 }).fill(0)

在答案中没有看到此方法,因此它是:

"0".repeat( 200 ).split("").map( parseFloat )

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

[ 0, 0, 0, 0, ... 0 ]

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

concat根据我在Chrome(2013-03-21)上的测试,版本的速度要快得多。10,000,000个元素大约需要200毫秒,而直接初始化则需要675毫秒。

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));
}

奖励:如果您想用字符串填充数组,这是一种简洁的方法(速度不快concat):

function filledArrayString(len, value) {
    return new Array(len+1).join(value).split('');
}

我正在测试TJ Crowder给出的最佳答案,并基于concat解决方案提出了一个递归合并,该解决方案的性能优于他在Chrome中进行的测试(我没有测试其他浏览器)。

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;
},

用调用方法makeRec(29)

new Array(51).join('0').split('')

可能值得指出的是,它Array.prototype.fill是作为ECMAScript 6(Harmony)提案的一部分添加的在考虑线程上提到的其他选项之前,我宁愿使用下面编写的polyfill。

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;
  };
}

循环代码最短

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版本

var a=[],i=0;for(;i<100;)a[i++]=0;

edit:
for(var i=100,a=[];i--;)a[i]=0;
let filled = [];
filled.length = 10;
filled.fill(0);

console.log(filled);

我最快的功能是:

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

与声明数组范围和引用每个项目以设置其值相比,使用本机的推入和移位向数组添加项目要快得多(约10倍)。

仅供参考:在firebug(firefox扩展程序)中运行此循环时,我一直在使用第一个循环(倒计时)获得更快的速度。

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

我很想知道TJ Crowder是做什么的?:-)

我知道我在某处有这个原型:)

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

var a = (new Array(5)).init(0);

var b = [].init(0,4);

编辑:测试

为了响应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();

结果:

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

因此,根据我的估算,推进通常确实较慢,但在FF中使用较长的数组时性能较好,但在IE中则差强人意(令人惊讶)。

匿名函数:

(function(n) { while(n-- && this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]

for循环要短一些:

(function(n) { for(;n--;this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]

适用于任何产品Object,只需更改其中的内容即可this.push()

您甚至可以保存该功能:

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

性能:http//jsperf.com/zero-filled-array-creation/25

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

文件下载

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

上一篇:
下一篇:

评论已关闭!