我有一个对象数组,可能会也可能不会在其属性中填充数组。在null x上调用$ .each(x,function(){})会导致类型错误
try{
var a = {};
$.each(a.doesnotexist,function(k,v){})
} catch(e) {
console.log(e.message)
}
我见过在空对象上使用$ .extend并将该值传递给$ .each()的建议。这两个似乎对我有用,看起来更简单,是否有任何缺点?
//some test values, not guaranteed properties are populated
var a = [
{v: [1,2,3,4,5], w: [1,2,3,4,5,6]},
{v: [1,2,3,4,5]},
{w: [1,2,3,4,5]},
{v: [1,2,3], w: []},
{v: null}
];
for (i =0; i < a.length; i++) {if (a[i].v) $.each(a[i].v,function(k,v){});}
for (i =0; i < a.length; i++) {$.each(a[i].v||[],function(k,v){});}
第二个对我来说似乎最干净。
答案 0 :(得分:1)
您可以使用in
operator来检查对象中是否存在属性。
for (var i = 0; i < a.length; ++i) {
if ("v" in a[i]){
$.each(a[i].v, function(k,v) {
...
});
}
}
并使用instanceof
operator检查正确的变量类型。
if ("v" in a[i] && a[i].v instanceof Array) { ... }
与短路评估相反,这种评估不易受到真正的影响。
$.each(a[i].v || [], ...);
答案 1 :(得分:0)
您甚至可以将第一个快捷方式设为
a[i].v && $.each(a[i].v, function(k,v){});
$.each
会对普通对象产生一些开销。
我的建议是制作一个类似于null的for
循环包装器:
function nullsafeForEach(arr, fun) {
var i, len;
if (!arr || !arr.length || !fun) {
return;
}
for (i = 0, len = arr.length; i < len; ++i) {
fun(arr[i]);
};
}
并考虑缓存a.length
答案 2 :(得分:0)
您可能是undefined
,而不是null
。在JavaScript中,尚未包含值的变量设置为undefined
。
就个人而言,我最喜欢解决方案#2。这就是我要做的。但是,您应该记住,如果这是其他人可能在将来维护的代码,那么使用方法#1并不会有什么坏处。方法#1在其正在进行的操作中更为明显,因此对于可能不熟悉逻辑运算符短路概念的人(例如||
)更易于维护。
此外,方法#2比方法#1慢得多,因为如果a[i].v
是falsy,它需要实例化一个空数组。但是开销可以忽略不计,所以除非出于某些原因这是性能关键或内存关键代码,否则你对方法#2没问题。
答案 3 :(得分:0)
另一种可能性是过滤第一个数组。
function hasV(item) { return !!item.v; }
function doWork(k, v) { /* do your work */ }
$.each($.grep(a, hasV), doWork);
或使用原生方法做同样的事情。
function hasV(item) { return !!item.v; }
function doWork(v, k) { /* do your work */ }
a.filter(hasV).forEach(doWork);
答案 4 :(得分:0)
这是一个更易读的版本(使用清晰,详细的检查),你可能想做什么
for(var i in a)
{
if(typeof a[i] == 'object' && typeof a[i].v != 'undefined')
{
$.each(a[i].v,function(k,v){ });
}
}
如果你想要真的很好,你还可以检查a[i].v
的长度以获得良好的衡量标准!