我正在使用JS数组将ID映射到实际元素,即键值存储。我想迭代所有元素。我尝试了几种方法,但都有其注意事项:
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 :(得分:4)
有三个问题:
for...in
to iterate arrays. 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
)或真正属于自己的属性。
答案 1 :(得分:4)
在for ... in
中使用hasOwnProperty
以确保不包含原型添加:
for (var item in map)
if (map.hasOwnProperty(item)) {
// do something
}
答案 2 :(得分:2)
1)使用已建议的对象,这是迄今为止最好的解决方案。
2)如果你出于某种原因需要使用一个数组 - 不要害怕用它循环
for(var i, len = arr.length;len < i;i++)
非常快。
3)如果你想要性能,不要使用$.each
或类似的方法 - 它们为每次迭代创建一个新的callstack,这是一个巨大的开销。
答案 3 :(得分: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;
};
答案 4 :(得分:0)
不要使用数组。请改用对象哈希
var map = {};
map[key] = value;
...
for (var key in map) {
do something to map[key]
}
答案 5 :(得分:0)
如果没有实际检查以查看值是否未定义然后执行操作a或操作b,则无法做很多事情。最好使用谓词来确定值是否未定义:
x = $.grep(x, function(v, i) { return (typeof(v) != "undefined"); });
答案 6 :(得分:-1)
没有。唯一的方法是完全省略集合中的项目,你提出的任何解决方案仍然需要对每个元素进行测试。
你可以想出不同的方法将项目键/值添加到对象文字或你有什么,但如果你不想枚举它们,你仍然需要省略未定义的条目。