我今天也对此感兴趣,但主要是因为我不喜欢在我已经知道我的对象是干净的(因为它们是从对象文字创建的)时必须使用 hasOwnProperty 测试来传递默认 lint。无论如何,我对@styonsk 的答案进行了一些扩展,以包含更好的输出并运行多个测试并返回输出。
结论:节点复杂。最好的时间看起来像是在 nodejs v4.6.1 上使用带有数字 for 循环或 while 循环的 Object.keys()。在 v4.6.1 上,带有 hasOwnProperty 的 forIn 循环是最慢的方法。但是,在节点 v6.9.1 上它是最快的,但它仍然比 v4.6.1 上的两个 Object.keys() 迭代器慢。
注意:这是在 2013 年末配备 16GB 内存和 2.4Ghz i5 处理器的 MacBook Pro 上运行的。在测试期间,每个测试都与单个 cpu 的 100% 挂钩,平均 rss 约为 500MB,峰值为 1GB 的 rss。希望这对某人有所帮助。
这是我针对具有大对象(10^6 个属性)和小对象(50 个属性)的 nodejs v6.9.1 和 v4.6.1 运行的结果
具有大对象 10^6 属性的节点 v4.6.1
testObjKeyWhileDecrement
测试次数: 100
总时间: 57595 毫秒
平均时间: 575.95 毫秒
testObjKeyForLoop
测试次数: 100
总时间: 54885 毫秒
平均时间: 548.85 毫秒
testForInLoop
测试次数: 100
总时间: 86448 毫秒
平均时间: 864.48 毫秒
具有小对象 50 个属性的节点 v4.6.1
testObjKeyWhileDecrement
测试计数: 1000
总时间: 4 毫秒
平均时间: 0.004 毫秒
testObjKeyForLoop
测试计数: 1000
总时间: 4 毫秒
平均时间: 0.004 毫秒
testForInLoop
测试计数: 1000
总时间: 14 毫秒
平均时间: 0.014 毫秒
具有大对象 10^6 属性的节点 v6.9.1
testObjKeyWhileDecrement
测试次数: 100
总时间: 94252 毫秒
平均时间: 942.52 毫秒
testObjKeyForLoop
测试次数: 100
总时间: 92342 毫秒
平均时间: 923.42 毫秒
testForInLoop
测试次数: 100
总时间: 72981 毫秒
平均时间: 729.81 毫秒
具有小对象 50 个属性的节点 v4.6.1
testObjKeyWhileDecrement
测试计数: 1000
总时间: 8 毫秒
平均时间: 0.008 毫秒
testObjKeyForLoop
测试计数: 1000
总时间: 10 毫秒
平均时间: 0.01 毫秒
testForInLoop
测试计数: 1000
总时间: 13 毫秒
平均时间: 0.013 毫秒
以下是我运行的代码:
//Helper functions
function work(value) {
//do some work on this value
}
function createTestObj(count) {
var obj = {}
while (count--) {
obj["key" + count] = "test";
}
return obj;
}
function runOnce(func, obj) {
var start = Date.now();
func(obj);
return Date.now() - start;
}
function testTimer(name, func, obj, count) {
count = count || 100;
var times = [];
var i = count;
var total;
var avg;
while (i--) {
times.push(runOnce(func, obj));
}
total = times.reduce(function (a, b) { return a + b });
avg = total / count;
console.log(name);
console.log('Test Count: ' + count);
console.log('Total Time: ' + total);
console.log('Average Time: ' + avg);
console.log('');
}
//Tests
function testObjKeyWhileDecrement(obj) {
var keys = Object.keys(obj);
var i = keys.length;
while (i--) {
work(obj[keys[i]]);
}
}
function testObjKeyForLoop(obj) {
var keys = Object.keys(obj);
var len = keys.length;
var i;
for (i = 0; i < len; i++) {
work(obj[keys[i]]);
}
}
function testForInLoop(obj) {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
work(obj[key]);
}
}
}
//Run the Tests
var data = createTestObj(50)
testTimer('testObjKeyWhileDecrement', testObjKeyWhileDecrement, data, 1000);
testTimer('testObjKeyForLoop', testObjKeyForLoop, data, 1000);
testTimer('testForInLoop', testForInLoop, data, 1000);