我一直在读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 情况,我可以看出这种比较可能是为了区分数组和对象,因为在 else 情况下它使用:
for (var key in obj) { ...
我看不出有任何理由使用这样的比较。谁能解释一下?
基本上,这是一种测试length
属性类型为Number
的方法,无需使用typeof
和该数字不是 NaN
。所以实际上:
if (typeof obj.length === "number" && !isNaN(obj.length))
比较 n === +n
只对数字为真,因为 ===
测试类型和值,而 +n
将创建一个 Number
(如您所见,可能是数字 NaN
)。因为 NaN === NaN
是假的,所以它也把那些都剔除了。
因此,根据一个定义(“具有不是 NaN
的数字 length
”),这是一种检测要迭代的对象是否为数组的方法-喜欢。在 JavaScript 和浏览器世界中有几种类似数组的东西,例如 arguments
伪数组和 DOM 的 NodeList
。
愚蠢的性能比较:
结果:没有 NaN
方面,typeof
更快(当类型错误时尤其如此)。对于 NaN
方面,+
在结果为 true
和为 false 时更快,因为它是 NaN
,并且当结果为 false
时速度较慢(明显如此),因为它是错误的类型。 (当然,歌剧一如既往地不同。)
并不是说它在现实世界中可能很重要(参见上面的“愚蠢”)。