在JavaScript中创建任意长度的零填充数组的最有效方法是什么?
let i = 0; Array.from(Array(10), ()=>i++);
在JavaScript中创建任意长度的零填充数组的最有效方法是什么?
let i = 0; Array.from(Array(10), ()=>i++);
Answers:
ES6介绍Array.prototype.fill
。可以这样使用:
new Array(len).fill(0);
不知道它是否很快,但是我喜欢它,因为它简短而自描述。
它仍然不在IE中(检查兼容性),但是有一个polyfill可用。
new Array(len)
太慢了 (arr = []).length = len; arr.fill(0);
是关于在任何地方都可以看到的最快的解决方案ive ...或至少并列
arr = Array(n)
并(arr = []).length = n
根据规范具有相同的行为。在某些实现中,速度可能会更快,但我认为没有太大的区别。
(arr = []).length = 1000;
进行arr = new Array(1000);
速度测试...这new
太慢了。现在,对于较小的数组长度..例如,<50或大约... new Array()
似乎确实表现更好。但是..
arr.fill(0)
……一切都发生了变化。现在,new Array()
在大多数情况下使用速度更快,除非您获得的数组大小> 100000 ...然后您可以开始看到速度再次提高。但是,如果您实际上不必用零预填充它,则可以使用空数组的标准伪造。(arr = []).length = x
在大多数情况下,然后在我的测试用例中就快疯了。
new Array(5).forEach(val => console.log('hi'));
VS new Array(5).fill(undefined).forEach(val => console.log('hi'));
。
尽管这是旧线程,但我想在其中加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]
Array.apply(null, new Array(5)).map(...)
?原因只是做(new Array(5))。map(...)不能按规范说明的那样工作
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
。
.apply
实际上是您想要的this
。出于这些目的,this
这无关紧要-我们只真正关心参数的扩展“功能” .apply
-因此它可以是任何值。我喜欢null
它,因为它很便宜,您可能不想使用它,{}
或者[]
因为您无缘无故实例化一个对象。
到目前为止,还没有人提到使用ES6的另一种方法:
> Array.from(Array(3), () => 0)
< [0, 0, 0]
通过将map函数作为的第二个参数来工作Array.from
。
在上面的示例中,第一个参数分配一个由3个位置组成的数组,这些位置填充有value 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]
repeat
绝对不会在生产中使用该技巧,但Array.from()
它非常好:-)
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位)。
下面我显示了最快浏览器(Safari)的搜索结果:
对于所有浏览器,最快的解决方案是M-但是它不是“典型数组”(但非常快)-Safari 33.8k次/秒,Chrome 5.2k,FF 3.5k,
典型阵列的最快解决方案:
最慢的解决方案:
解决方案N仅适用于Firefox和Chrome。
最快的:
最慢的:
n
Firefox上的小型浏览器以外)最快的解决方案是M let a = new Float32Array(n)
(但不是典型的阵列)-为此,最快的浏览器是Safari(大型浏览器的n
速度比Chrome快6倍,比firefox快9倍)let a = Array(n).fill(0)
(快速和短代码) 您可以在此处对机器进行测试。
let a=[]; for(i=n;i--;) a.push(0);
但它的速度慢了4倍fill(0)
-因此,我什至不会更新该情况的图片。
已经提到的ES 6填充方法很好地解决了这一问题。到目前为止,大多数现代桌面浏览器已经支持所需的Array原型方法(Chromium,FF,Edge和Safari)[ 1 ]。您可以在MDN上查找详细信息。一个简单的用法示例是
a = new Array(10).fill(0);
鉴于当前的浏览器支持,除非您确定您的受众使用的是现代桌面浏览器,否则应谨慎使用。
a = Array(10).fill(null).map(() => { return []; });
a = Array(10).fill(0).map( _ => [] );
注意于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>
默认情况下Uint8Array
,Uint16Array
和Uint32Array
类将零保留为其值,因此您不需要任何复杂的填充技术,只需执行以下操作:
var ary = new Uint8Array(10);
ary
默认情况下,数组的所有元素将为零。
Array.isArray(ary)
is)一样对待false
。该长度也是只读的,因此不能像ary.push
0
为默认值。
Array.from(new Uint8Array(10))
将提供一个普通数组。
Array(n).fill(0)
如果您真正需要的是JS数组,那比Chrome 慢5倍。如果可以使用TypedArray,则速度甚至比快得多.fill(0)
,尤其是如果可以使用默认的初始化值0
。似乎没有像C ++那样std::vector
具有填充值和长度的构造函数。似乎对于任何非零值,您都必须构造一个调零的TypedArray,然后填充它。:/
如果使用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-in
,forEach
等等。
i
局部变量不是多余的吗? length
通过值传递,因此您应该可以直接将其递减。
arr[i] = value
)分配值非常慢。从头到尾遍历并使用快得多arr.push(value)
。这很烦人,因为我更喜欢您的方法。
使用对象符号
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 = [];
将进行原型修改
无论如何,我不会过分担心此操作的效率或速度,您可能会做很多其他事情,这些事情比实例化包含零的任意长度的数组要浪费得多,也更昂贵。
null
此数组中没有s –var x = new Array(7);
new Array(7)
并没有建立一个数组“充满了不确定的”。它创建一个空的与长度7.阵列
(new Array(10)).fill(0)
。
我已经测试了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;
}
var array = []
声明实际放入for循环的第一部分,仅以逗号分隔。
length
已给定的值,以使其不会不断变化。在我的机器上将一百万个长度为零的数组从40ms扩展为8。
for (i = 0, array = []; i < length; ++i) array[i] = val;
..更少的方块?...无论如何,...如果我将array.length
新数组的长度设置为长度..我似乎在FF中又增加了10%-15%的速度...在Chrome中,速度似乎翻了一番-> var i, array = []; array.length = length; while(i < length) array[i++] = val;
(如果我将其保留为for
循环会更快一些,但是不再需要init了,所以while
在这个版本上
function zeroFilledArray(size) {
return new Array(size + 1).join('0').split('');
}
new Array(size+1).join("x").split("x").map(function() { return 0; })
来获取实际数字
new Array(size+1).join('0').split('').map(Number)
如果您需要在执行代码的过程中创建许多不同长度的零填充数组,我发现实现此目标的最快方法是使用本主题中提到的一种方法,一次创建一个零数组,其长度为您知道永远不会超出它,然后根据需要切片该数组。
例如(使用上面选择的答案中的函数初始化数组),创建一个长度为maxLength的零填充数组,作为需要零数组的代码可见的变量:
var zero = newFilledArray(maxLength, 0);
现在,每当您需要长度为requiredLength < maxLength的零填充数组时,就对它进行切片:
zero.slice(0, requiredLength);
在执行代码期间,我数千次创建了零填充数组,这极大地加快了处理速度。
我没有反对:
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
Firefox 20.0
缺少最重要的测试(至少对我而言):Node.js。我怀疑它接近Chrome基准测试。
从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
变量即会。该MDN和Airbnb的风格指南是伟大的地方去的最佳实践的详细信息。问题不是语法,而是新接触JS的人们在搜索大量新旧答案时了解这些新标准很重要。
创建一个全新的阵列
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)]);
在答案中没有看到此方法,因此它是:
"0".repeat( 200 ).split("").map( parseFloat )
结果,您将获得长度为200的零值数组:
[ 0, 0, 0, 0, ... 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版本
var a=[],i=0;for(;i<100;)a[i++]=0;
edit:
for(var i=100,a=[];i--;)a[i]=0;
n
它会更短:for(var a=[];n--;a[n]=0);
我最快的功能是:
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是做什么的?:-)
while (len--)
..将我的处理时间从大约60ms更改为大约54ms 来加快速度
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)
。
可能值得指出的是,这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;
};
}
let filled = [];
filled.length = 10;
filled.fill(0);
console.log(filled);
我知道我在某处有这个原型:)
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中则差强人意(令人惊讶)。
b = []...
)比第一种方法快10-15%,但比Joshua的答案慢10倍以上。
else {this.length=n;}
进行一些this.length
补充:在-check 之后添加一个。如果需要重新init
将其重新格式化为其他长度,这将缩短已经存在的数组n
。
匿名函数:
(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']