Javascript for..in vs for loop performance

Jos*_*hin 15 javascript

我使用kmean算法聚集了大约40000点.在程序的第一个版本中,我像这样编写了欧几里德距离函数

var euclideanDistance = function( p1, p2 ) { // p1.length === p2.length == 3
    var sum = 0;
    for( var i in p1 ){
        sum += Math.pow( p1[i] - p2[i], 2 );
    }
    return Math.sqrt( sum );
};
Run Code Online (Sandbox Code Playgroud)

整个程序非常缓慢,平均执行时间为7秒.经过一些分析后,我重写了上面这个函数

var euclideanDistance = function( p1, p2 ) { // p1.length === p2.length == 3
    var sum = 0;
    for( var i = 0; i < p1.length; i++ ) {
        sum += Math.pow( p1[i] - p2[i], 2 );
    }
    return Math.sqrt( sum );
};
Run Code Online (Sandbox Code Playgroud)

现在这些节目平均需要大约400毫秒.由于我编写for循环的方式,这是一个巨大的时间差异.我通常不使用for..in循环数组但由于某种原因我在编写此函数时使用它.

有人可以解释为什么这两种风格之间存在巨大的性能差异吗?

Esa*_*ija 24

看看每次迭代中发生的事情有何不同:

for( var i = 0; i < p1.length; i++ ) 
Run Code Online (Sandbox Code Playgroud)
  1. 检查是否 i < p1.length
  2. 增加i一个

非常简单快速.

现在看看每次迭代中发生了什么:

for( var i in p1 )

重复

  1. 令P为obj的下一个属性的名称,其[[Enumerable]]属性为true.如果没有这样的属性,则返回(正常,V,空).

它必须在可枚举的对象中找到下一个属性.使用你的数组,你知道这可以通过一个简单的整数增量来实现,其中找到下一个可枚举的算法很可能不那么简单,因为它必须处理任意对象及其原型链键.

  • 这是模糊的,不确定这里发生了什么 (2认同)

gki*_*ely 7

作为旁注,如果缓存p1的长度:

var plen = p1.length;
for( var i = 0; i < plen; i++ )
Run Code Online (Sandbox Code Playgroud)

你的速度会略有提高.

...如果您记住该功能,它将缓存结果,因此如果用户尝试相同的数字,您将看到大幅度的速度增加.

var eDistance = memoize(euclideanDistance);  

function memoize( fn ) {  
    return function () {  
        var args = Array.prototype.slice.call(arguments),  
            hash = "",  
            i = args.length;  
        currentArg = null;  
        while (i--) {  
            currentArg = args[i];  
            hash += (currentArg === Object(currentArg)) ?  
            JSON.stringify(currentArg) : currentArg;  
            fn.memoize || (fn.memoize = {});  
        }  
        return (hash in fn.memoize) ? fn.memoize[hash] :  
        fn.memoize[hash] = fn.apply(this, args);  
    };  
}

eDistance([1,2,3],[1,2,3]);
eDistance([1,2,3],[1,2,3]); //Returns cached value
Run Code Online (Sandbox Code Playgroud)

信用:http://addyosmani.com/blog/faster-javascript-memoization/


op1*_*kun 5

首先,对于 for/in 和数组,您应该意识到这一点。如果您知道自己在做什么,那没什么大不了的。

我运行了一些非常简单的测试来显示不同循环之间的性能差异:http : //jsben.ch/#/BQhED

这就是为什么更喜欢对数组使用经典的 for 循环的原因。