我一直在阅读underscore.js源代码,并注意到_.each():
(obj.length === +obj.length)
我知道在变量转换为数字/整数之前+。所以在这个原因
[1,2,3].length === +[1,2,3].length
是真的。如果我传入一个对象:
var obj = {a: 1, b: 2, c: 3};
+obj.length
生成 NaN
在最后一种情况下,我有
[1,2,3, {a: [4,5,6]}].length
这是4.将它投射到一个数字..仍然是4.
从 else case 决定,我可以看到这种比较可能是为了区分数组和对象,就像它使用的其他情况一样:
for (var key in obj) { ...
我没有看到任何使用这种比较的理由。谁能解释一下?
答案 0 :(得分:6)
基本上,这是一种测试length
属性类型为Number
的方法,而不使用typeof
和,但该数字不是{{1} }。所以实际上:
NaN
比较if (typeof obj.length === "number" && !isNaN(obj.length))
仅适用于某个数字,因为n === +n
会测试类型和值,而===
会创建+n
(可能就像您找到的那样) ,数字Number
)。而且因为NaN
是假的,所以它也会将它们除掉。
所以这是一种检测方法,根据一个定义(“有一个不是NaN === NaN
的数字length
”),要迭代的对象是否为array- < / em>的。 JavaScript和浏览器世界中有几个类似于数组的东西,例如NaN
伪数组和DOM的arguments
。
愚蠢的表现比较:
NodeList
与+
而不用担心typeof
:When true
| When false
NaN
与+
和typeof
:When true
| When false
(wrong type) | When false
(NaN
) Upshot:没有isNaN
方面,NaN
更快(当类型错误时显然更快)。使用typeof
方面,NaN
在结果为+
时会更快,而当它为true
时会更慢,而在结果为NaN
时会更慢(显着)是false
,因为它是错误的类型。 (歌剧当然一如既往地不同。)
并不是说它在现实世界中很重要(见上文“愚蠢”)。
答案 1 :(得分:1)
我认为这是区分Object
实例与Array
实例或' Arrayish '对象(如arguments
)的快速方法。
如果Object
实例包含length
属性,它将会中断。与{a:1, length: 1}
一样,或[].push.call({},'a value')
的结果(结果如下:{0:'a value',length: 1}
)。如this jsFiddle
答案 2 :(得分:1)
从上下文来看,我认为它试图弄清楚obj
是否是一个数组,因为迭代一个数组需要一个顺序for
循环而不是for
- in
:https://stackoverflow.com/a/3010848/367273
答案 3 :(得分:0)
+运算符返回对象的数字表示。因为你的代码+ obj.length意味着它返回一个数字引用.... this。你得到一个数组时,+ obj.length值为Number,但如果var obj = {a:1,b:2,c:3}则不返回长度;因为它不是一个数组......当你使用[1,2,3,{a:[4,5,6]}]。长度时它返回4作为对象在数组中......