我正在研究very, very, very simple library以提供一些便利功能来处理本机JavaScript对象,理想情况下(最终)以类似jQuery的方式。
我有一个简单的函数:crawlObject
我修改为使用jQuery的each()
而不是for(var key in obj)
循环。
function crawlObject(thisObj, onSuccess, doRecursion) {
var stopCrawling = false;
if (isFunction(onSuccess) && ($.isPlainObject(thisObj) || isArray(thisObj))) {
$.each(thisObj, function(childKey, value) {
var childObj = thisObj[childKey];
if (false === stopCrawling) {
stopCrawling = isTrue(onSuccess(childObj, childKey, thisObj, value));
}
if (false === stopCrawling && doRecursion) {
stopCrawling = isTrue(crawlObject(childObj, onSuccess, doRecursion));
}
});
}
return stopCrawling;
}
这具有爬行Array对象和“普通”JS对象而无需额外逻辑的优点。
但是
如果我传递的“普通”JS对象碰巧有一个属性名称为'length',则每个()内爆就像一个功能失调的凤凰。如果我在定义DOM元素的大对象上进行递归,则可能会发生这种情况,DOM元素可能包含用于指示UI中字符显示长度的length属性。这里的值为200是灾难性的:突然每个()在道具的值上迭代0-199。
在我投资任何进一步的重构之前,有没有人偶然找到解决这个问题的方法?
答案 0 :(得分:3)
jQuery的documentation for jQuery.each()清楚地指出,如果对象具有.length
属性,那么它将从0到长度为1的数字索引进行迭代(就像您对数组或类数组对象所期望的那样) 。
如果你有一个.length
属性的对象,你要迭代的东西不是从0到长度为1的数字索引,那么jQuery.each()
将不会做你想要的,你不应该使用它。
以下是jQuery源代码中jQuery.each()
的具体代码。您可以在函数的第2行和第3行看到,如果有object.length
,isObj
将是false
,并且以后它不会被视为对象:
// args is for internal usage only
each: function( object, callback, args ) {
var name, i = 0,
length = object.length,
isObj = length === undefined || jQuery.isFunction( object );
if ( args ) {
if ( isObj ) {
for ( name in object ) {
if ( callback.apply( object[ name ], args ) === false ) {
break;
}
}
} else {
for ( ; i < length; ) {
if ( callback.apply( object[ i++ ], args ) === false ) {
break;
}
}
}
// A special, fast, case for the most common use of each
} else {
if ( isObj ) {
for ( name in object ) {
if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
break;
}
}
} else {
for ( ; i < length; ) {
if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
break;
}
}
}
}
return object;
},
答案 1 :(得分:0)
我认为如果(thisObj.hasOwnProperty(“length”))可能会为你做这件事