我的印象是只有Array
对象有一个.length
财产。但是,话又说回来,我也看到过提到“类似数组”的对象。我还没有研究过这个,现在看来我对 JS 中这个话题的无知可能让我很痛苦。例证:
我有以下代码:
var View = function(options) {
// code
};
_.extend(View, Backbone.Events, {
make_children: function(parent) {
// code
}
});
后来我就用这个View
Function
带有下划线的_.each
,这决定了这个函数对象是一个数组,因为它有一个.length
财产:
// Code from Underscore.js's `_.each`:
} else if (obj.length === +obj.length) { // This is true
for (var i = 0, l = obj.length; i < l; i++) { // **So, execution goes here**
if (iterator.call(context, obj[i], i, obj) === breaker) return
}
} else {
for (var key in obj) {
if (_.has(obj, key)) { // **Execution does __not__ go here**
if (iterator.call(context, obj[key], key, obj) === breaker) return;
}
}
}
这会导致代码不起作用,因为obj[i]
where i
是一个整数索引,实际上并未在我的上定义obj
View
。准确地说,在上面的代码中,obj[0]
is undefined
while obj.length === +obj.length
is true
and obj.length
is 1
。这里发生了什么?
Addendum
Underscore 的首席维护者在https://github.com/documentcloud/underscore/pull/510 https://github.com/documentcloud/underscore/pull/510:
简单地创建每个拒绝函数对象并没有真正的帮助。我们已经
有意识地决定使用数字长度属性来检测
类似数组的对象。
相反,不要将函数对象传递给each
.
附录2
意识到因为我无法将函数对象传递给_.each
,我可以将其“转换”为常规对象,如下所示:
var regular_obj = _.extend({}, View);