JavaScript中的哪些对象具有.length属性? (又名为什么Underscore _.each将我的函数对象视为数组?) [英] Which Objects in JavaScript have a .length property? (aka Why does Underscore _.each treat my Function Object like an Array?)
问题描述
我一直认为只有 Array
对象才有 .length
属性。但是,我再次看到提到阵列式的对象。我没有调查过这个,现在看来我对JS中这个话题的无知可能会让我陷入困境。例证:
I've been under the impression that only Array
objects have a .length
property. But, then again, I've also seen mentions of objects that are "array-like". I've not looked into this, and now it seems like my ignorance of this topic in JS may be biting me in the ass. Case in point:
我有以下代码:
var View = function(options) {
// code
};
_.extend(View, Backbone.Events, {
make_children: function(parent) {
// code
}
});
稍后,我使用此查看
函数
使用Underscore的 _。每个
,它决定这个函数对象是一个数组,因为它有一个 .length
property:
Later on, I use this View
Function
with Underscore's _.each
, which decides this function object is an array, because it has a .length
property:
// 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
是一个整数索引,实际上并没有在我的<$上定义c $ c> obj 查看
。确切地说,在上面的代码中, obj [0]
是 undefined
而 obj。长度=== + obj.length
是 true
和 obj.length
是 1
。这里发生了什么?
This results in code that doesn't work, because obj[i]
where i
is an integer index, is not actually defined on my obj
View
. To be precise, in the above code, obj[0]
is undefined
while obj.length === +obj.length
is true
and obj.length
is 1
. What's going on here?
附录
Underscore的主要维护人员说以下内容 https://github.com/documentcloud/underscore/pull/510 :
Underscore's chief maintainer says the following on https://github.com/documentcloud/underscore/pull/510:
简单地制作每个拒绝功能对象并没有多大帮助。我们
有意识地决定使用数字长度属性来检测
类似数组的对象。
Simply making each reject function objects doesn't really help. We've made a conscious decision to use a numerical length property to detect array-like objects.
相反,不要传递函数对象每个
。
Instead, don't pass function objects to each
.
附录2
意识到由于我无法将函数对象传递给 _。每个
,我只能投了它像这样的常规对象:
Realized that since I couldn't pass a function object to _.each
, I could just "cast it" to a regular object like so:
var regular_obj = _.extend({}, View);
推荐答案
这里的问题是 underscore.js
,就像 jquery
一样,都使用 .length
属性作为标志在他们的每个
函数中。当存在 length
属性时,该函数假定传递的参数可以通过正常的for循环进行迭代。这个逻辑背后的原因是期望当定义 length
属性时,可以按顺序遍历参数 ,这是为什么使用for循环。
The issue here is that underscore.js
, much like jquery
, both use the .length
property as a flag in their each
functions. When the length
property is present, the function assumes that the argument passed can be iterated through with a normal for loop. The reason behind this logic is there is an expectation that when the length
property is defined then it is possible to iterate through the argument in order which is why the for loop is used.
滥用 length
的结果本质上是名称冲突,其中存在意外结果。我建议将长度
更改为另一个同义词,例如 size
或 capacity
或 totalViews
等。
The result of misusing length
is essentially a name collision where there is an unintended result. I would suggest changing length
to another synonym such as size
or capacity
or totalViews
, etc.
编辑
如果没有其他替代供您使用,并且您必须有长度,同时仍保留 _。每个
的功能,然后你可以稍微破解它。此插件适用于下划线版本1.4.3的缩小版本。
If there are no other alternatives for you to use, and you must have length in there while still retaining _.each
's functionality, then you can slightly hack it. This plug works with the minified version of underscore version 1.4.3
var s = Array.prototype.ForEach;
var r = {};
var myEach = function (n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length&&typeof(n[0])!="undefined"){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(_.has(n,a)&&t.call(e,n[a],a,n)===r)return};
_.each=myEach;
这是一个演示: http://jsfiddle.net/Xa5qq/
它的作用基本上是使用 forEach
当 length
属性存在但 typeof(yourObject [0])==undefined
时。
Basically what it does is use forEach
when the length
property exists but typeof(yourObject[0]) == "undefined"
.
这篇关于JavaScript中的哪些对象具有.length属性? (又名为什么Underscore _.each将我的函数对象视为数组?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!