array.forEach(callbackFunction)
。它不执行零到数组长度之间每个索引的callbackFunction
,而只针对实际in
数组中的键执行。(告诉我是否错误) 这些键正好是Object.keys(array)
将给我的。因此(告诉我为什么我错了),如果在array
本身上调用.forEach
方法或者在Object.keys(array)
上调用,就不应该有任何差别。所以,为什么地球上会有这样的性能差异——好像在一个情况下,从零到长度的一个巨大无意义的循环会被执行,但在另一个情况下却不会被执行。
演示性能差异的代码片段:
function doNothing(){}
CONSOLE = document.getElementById('console');
arr = [];
arr[49888999] = 42;
start = performance.now();
arr.forEach(doNothing);
duration1 = performance.now() - start;
start = performance.now();
Object.keys(arr).forEach(doNothing);
duration2 = performance.now() - start;
CONSOLE.textContent = [duration1, duration2].join('\n');
<pre id='console'></pre>
代码片段展示了回调函数在两种情况下仅被调用一次
console1 = document.getElementById('console1');
console2 = document.getElementById('console2');
function doNothingVerbose1(){
console1.textContent = 1 + (+console1.textContent);
}
function doNothingVerbose2(){
console2.textContent = 1 + (+console2.textContent);
}
arr = [];
arr[49888999] = 42;
start = performance.now();
arr.forEach(doNothingVerbose1);
duration1 = performance.now() - start;
start = performance.now();
Object.keys(arr).forEach(doNothingVerbose2);
duration2 = performance.now() - start;
console.log(duration1, duration2);
~~~~~ 1 ~~~~~
<pre id='console1'>0</pre>
~~~~~ 2 ~~~~~
<pre id='console2'>0</pre>
更新
我刚刚进行了一项测试,以找出上述arr=[];arr[49888999]=42;
是否为实际的稀疏数组,即相比于使用arr=new Array(49889000)
具有更小的内存占用。是的,事实确实如此。在循环中执行这种操作数百次,稀疏版本需要几秒钟但不会崩溃,但new Array(5000万)
版本会使fiddle崩溃。因此,如果它没有被存储为引擎中的“普通C ++数组”,那么引擎必须“拥有”该数组的Object.keys
,为什么引擎不充分利用它呢?我可能对JS引擎的工作过于简单化了;说它必须“拥有”Object.keys
是错误的,因为它以某种方式支持我们的变量arr
的“稀疏”数组实现吗?也许实际在浏览器/ JS引擎上工作的人可以在这里提供一些帮助。
Object.defineProperty(arr,'42',{enumerable:false})
,它仍应通过此非枚举的42
索引,并且如果您执行了arr [“foo”] = bar
,则应忽略此foo
属性。 - Kaiidoa = []; a.foo = "bar";
就可以了。 - KaiidoObject.defineProperty( arr, '42', { enumerable: false } )
https://jsfiddle.net/burt241f/ - KaiidoObject.keys()
看起来对我来说像是一种反模式。如果我发现自己处于这种情况下,我可能会使用普通对象而不是稀疏数组。 - Lennholm