2012-11-21 68 views
6

我已經在幾個地方看到,for-in循環比循環遍歷數組的速度慢......雖然我知道在sizeof(type)塊中向前移動與在場景後面迭代遍歷對象的鍵,我仍然好奇,究竟是什麼原因,它是如此之慢...爲什麼在JavaScript中輸入緩慢?

它是否必須做一個反向哈希函數來獲得密鑰,並且該過程是什麼慢?

+2

是的,我猜想得到所有的鍵是一個相對緩慢的過程相比......沒有得到它們;)for ... in'必須首先查找鍵,而使用正常的'for'循環,你正在通過循環變量提供密鑰。 –

+2

這是一個JSPerf測試,它顯示'for ... in'的運行與'Object.keys()'(至少在Chrome中)幾乎相同:http://jsperf.com/for-in- VS-鍵-VS-的。所以,獲取鑰匙和/或與此相關的一切都比較慢,並且從外部提供鑰匙。但它也取決於實施,就像T.J.說。 –

回答

3

在任何特定引擎的情況下,真正的答案可能取決於該引擎的實現。 (如果有的話,差異的大小也會如此)。

但是,有不變量。例如,考慮:

var obj = {a: "alpha", b: "beta"}; 
var name; 
for (name in obj) { 
    console.log(obj[name]); 
} 

var arr = ["alpha", "beta"]; 
var index; 
for (index = 0; index < arr.length; ++index) { 
    console.log(arr[index]); 
} 

obj的情況下,發動機必須使用一種機制來跟蹤哪些屬性你已經遍歷,哪些還沒有,以及過濾掉不可枚舉的屬性。例如,幕後有一些迭代器對象(以及spec定義的方式,可能是臨時數組)。

arr的情況下,它沒有;您正在以一種非常簡單而有效的方式在您的代碼中處理這些問題。

每個循環的塊內容是相同的:對象的屬性查找。 (在後一種情況下,理論上也有一個數字到字符串的轉換。)

所以我期望唯一的非實現特定的答案是:額外的開銷。

1

for..each循環使用iterators and generators

迭代器是一個具有next()方法的對象。 Generator是包含yield()表達式的工廠函數。這兩個構造比一個整數索引變量更復雜。

在典型for(var i = 0; i < arr.length; i++)循環,即在執行兩個指令幾乎所有迭代i++i < arr。這可以說比進行函數調用要快得多(next()yield())。

此外,循環初始化(var i = 0)也比用迭代器對象創建迭代器對象更快,或者調用生成器來創建迭代器。但是,它高度依賴於實現,JavaScript引擎的創建者盡其所能地加速這些常用語言功能。

我想說這種差異是如此的微不足道,以至於我可能會花時間優化代碼的其他部分。語法的選擇應該考慮代碼的可讀性和可維護性而不僅僅是性能,當性能增益如此之小以增加複雜性時。話雖如此,使用更有意義的語法,您和其他開發人員在您豐富和着名後維護您的代碼! ;)