我今天对此也很感兴趣,主要是因为我不喜欢在已知对象干净(因为它们是从对象字面量创建的)时仍然需要使用hasOwnProperty进行默认检测。无论如何,我对@styonsk的答案进行了扩展,包括更好的输出和运行多个测试并返回输出。
结论:对于Node来说这很复杂。最佳方法似乎是在nodejs v4.6.1上使用Object.keys()与数字for循环或while循环。在v4.6.1上,使用hasOwnProperty的forIn循环是最慢的方法。但是,在node v6.9.1上它是最快的,但仍然比v4.6.1上的两个Object.keys()迭代器慢。
注:这是在2013年底发布的MacBook Pro上运行的,配备16GB内存和2.4Ghz i5处理器。每个测试都占用了一个CPU核心的100%,持续时间约为500MB,并峰值达到1GB的rss。希望这能帮助某些人。
以下是我的结果,针对具有大量属性(10^6)和少量属性(50)的nodejs v6.9.1和v4.6.1运行。
Node v4.6.1具有100万属性的大对象
测试对象键名(使用while递减)
测试次数:100
总时间:57595毫秒
平均时间:575.95毫秒
测试对象键名(使用for循环)
测试次数:100
总时间:54885毫秒
平均时间:548.85毫秒
测试for-in循环
测试次数:100
总时间:86448毫秒
平均时间:864.48毫秒
Node v4.6.1具有50个属性的小对象
测试对象键名(使用while递减)
测试次数:1000
总时间:4毫秒
平均时间:0.004毫秒
测试对象键名(使用for循环)
测试次数:1000
总时间:4毫秒
平均时间:0.004毫秒
测试for-in循环
测试次数:1000
总时间:14毫秒
平均时间:0.014毫秒
Node v6.9.1具有100万属性的大对象
测试对象键名(使用while递减)
测试次数:100
总时间:94252毫秒
平均时间:942.52毫秒
测试对象键名(使用for循环)
测试次数:100
总时间:92342毫秒
平均时间:923.42毫秒
测试for-in循环
测试次数:100
总时间:72981毫秒
平均时间:729.81毫秒
Node v4.6.1具有50个属性的小对象
测试对象键名(使用while递减)
测试次数:1000
总时间:8毫秒
平均时间:0.008毫秒
测试对象键名(使用for循环)
测试次数:1000
总时间:10毫秒
平均时间:0.01毫秒
测试for-in循环
测试次数:1000
总时间:13毫秒
平均时间:0.013毫秒
以下是我运行的代码:
function work(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('');
}
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]);
}
}
}
var data = createTestObj(50)
testTimer('testObjKeyWhileDecrement', testObjKeyWhileDecrement, data, 1000);
testTimer('testObjKeyForLoop', testObjKeyForLoop, data, 1000);
testTimer('testForInLoop', testForInLoop, data, 1000);