我一直认为只有Array
对象才有.length
属性。但是,话又说回来,我还看到提到“类似数组”的对象。我还没有研究过这个,现在看来我对 JS 中这个话题的无知可能会咬我的屁股。一个例子:
我有以下代码:
var View = function(options) {
// code
};
_.extend(View, Backbone.Events, {
make_children: function(parent) {
// code
}
});
稍后,我将它View
Function
与 Underscore 一起使用_.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]
在哪里i
实际上并没有在我的obj
View
. 准确地说,在上面的代码中,obj[0]
is undefined
while obj.length === +obj.length
istrue
和obj.length
is 1
。这里发生了什么?
附录
Underscore 的首席维护者在https://github.com/documentcloud/underscore/pull/510上说:
简单地制作每个拒绝函数对象并没有真正的帮助。我们有意识地决定使用数值长度属性来检测类似数组的对象。
相反,不要将函数对象传递给
each
.
附录 2
意识到由于我无法将函数对象传递给_.each
,因此我可以将其“强制转换”为常规对象,如下所示:
var regular_obj = _.extend({}, View);