2011-01-12 40 views
3

我正在使用JS數組將ID映射到實際元素,即鍵值存儲。我想遍歷所有元素。我試了幾種方法,但都有其注意事項:迭代JS數組的已定義元素

for (var item in map) {...} 

是否遍歷數組的所有屬性,因此它也包括功能和擴展應用到Array.prototype。例如,未來有人在Prototype庫中放棄了現有代碼。

var length = map.lenth; 
for (var i = 0; i < length; i++) { 
    var item = map[i]; 
    ... 
} 

確實具有可怕的缺點的工作,但就像

$.each(map, function(index, item) {...}); 

他們遍歷整個範圍指標0..MAX(ID)的:

var x = []; 
x[1]=1; 
x[10]=10; 
$.each(x, function(i,v) {console.log(i+": "+v);}); 

0: undefined 
1: 1 
2: undefined 
3: undefined 
4: undefined 
5: undefined 
6: undefined 
7: undefined 
8: undefined 
9: undefined 
10: 10 

當然還有我的ID也不會像連續的序列。此外,它們之間可能存在巨大差距,因此在後一種情況下跳過未定義的性能原因是不可接受的。怎樣才能安全地遍歷數組的已定義元素(以適用於所有瀏覽器和IE的方式)?

+0

是正確的數字順序代碼中的一個問題? – user113716 2011-01-12 17:31:03

+0

不,這是一張無序的地圖,我不在乎訂購。我唯一擔心的是迭代已定義的元素和僅定義的元素。 – sibidiba 2011-01-12 17:43:02

+2

相關討論http://stackoverflow.com/questions/368280/javascript-hashmap-equivalent – goat 2011-01-12 18:01:21

回答

4

使用hasOwnPropertyfor ... in確保原型添加不包括:

for (var item in map) 
    if (map.hasOwnProperty(item)) { 
    // do something 
    } 
-1

沒有。唯一的辦法是完全省略集合中的項目,你提出的任何解決方案都必須對每個元素進行測試。

你可以想出不同的方法將項目鍵/值添加到對象文字或你有什麼,但如果你不想枚舉它們,你仍然需要省略未定義的條目。

0

請勿使用數組。使用對象的哈希,而不是

var map = {}; 
map[key] = value; 
... 
for (var key in map) { 
    do something to map[key] 
} 
+1

數組也是對象。 – casablanca 2011-01-12 17:30:23

+0

這正是我正在做的。沒有區別。 for(var key in map)也會返回對象的/數組的成員函數。 – sibidiba 2011-01-12 17:44:30

4

有三個問題:

  1. You should not use for...in to iterate arrays.
  2. 您正在使用您的要求錯誤的數據類型。
  3. 您未正確使用for...in

如果你想擁有像哈希表,然後使用普通object

var map = {}; 
map[123] = 'something'; 
map.foo = 'bar'; 
// same as map['foo'] = 'bar'; 
//... 

它看起來像一個數組,但事實並非如此。這是一個物業123。您可以使用點符號obj.key(僅當密鑰是有效標識符時 - 123無效,因此您必須使用下列符號)或數組符號obj['key']來訪問對象屬性。

看來,一個對象將是一個更合適的數據結構。

但即使如此,你應該對hasOwnProperty通話(每次使用for...in):

for(var key in obj) { 
    if(obj.hasOwnProperty(key)) { 
     //do something 
    } 
} 

此檢查屬性是否是從原型繼承(它將返回false當時)或者是真正的自己的財產。

0

你不能做很多沒有實際做了檢查,看是否值是不確定的,然後做操作或操作b。這將是更好地使用謂詞來確定是否值是不確定的:

x = $.grep(x, function(v, i) { return (typeof(v) != "undefined"); }); 
2

1)使用一個對象就像已經提出,它是迄今爲止最好的解決方案。

2)如果你因爲某些原因需要使用數組 - 不要害怕循環在它與

for(var i, len = arr.length;len < i;i++) 

這是非常非常快。

3)如果需要性能,請不要使用$.each或類似的方法 - 它們爲每次迭代創建一個新的callstack,這是一個巨大的開銷。

2

使用的EcmaScript 5內置Object.keys,並且在非ES5的瀏覽器,從而將其定義:

Object.keys = function (o) { 
    var keys = []; 
    var hasOwnProp = Object.prototype.hasOwnProperty; 
    if (Object.prototype.toString.call(o) === '[object Array]') { 
    for (var k in o) { 
     if (+k === (k & 0x7fffffff) && hasOwnProp.call(o, k)) { 
     keys[keys.length] = k; 
     } 
    } 
    keys.sort(keys, function (a, b) { return a - b; }); 
    } else { 
    for (var k in o) { 
     if (hasOwnProp.call(o, k)) { 
     keys[keys.length] = k; 
     } 
    } 
    } 
    return keys; 
};