2012-03-21 31 views
3

这让我感到惊讶:怪异array.length替代语法

var parts = email.split('@'); 
if (parts < 2) { 

参考:https://github.com/Kicksend/mailcheck/blob/master/src/jquery.mailcheck.js#L21-22

本质上来说,它看起来像:

var a = [null, null, null] 
a < 2 // false 

var b = [null] 
b < 2 // true 

所以它看起来像它的工作原理,但我想要知道为什么,实际上发生了什么强制呢?因为这里的意图是要保释,如果少于2个部分来自电子邮件字符串,我会期望它总是通过,因为数组定义为truthy - 它应该创建一个数组,至少有一个成员甚至在一个空字符串。

我总是喜欢用array.length。是以上安全吗?

+1

好吧,'array.length'并不总是安全的,或者考虑到它不会总是重新调整时删除一个元素;) – 2012-03-21 21:59:50

+1

@JeffreySweeney - '.length'总是表示数组的实际长度。如果一个元素被'.splice()'或'.pop()'移除,那么'.length'将立即可靠地返回新的长度。如果仅仅将数组元素设置为undefined,则该数组元素仍然存在,并且所有其他数组元素保留在相同的位置,因此'.length'值正确不会更改。你能否描述一下当你认为'.length'不准确时。 – jfriend00 2012-03-21 22:18:30

+0

感谢您的回复,完成完整性检查,问题提交,我不会疯狂...... – 2012-03-21 22:22:44

回答

4

这是一个字符串,然后数转换发生的事情,因为数组不能directy与<运营商相比。首先它会做一个字符串比较,然后用数字进行数字比较。

需要注意的是:

  • [null, null, null] == ",,"
  • [null] == ""

和:

  • +",,"NaN
  • +"" === 0

现在它是有道理的,因为0 < 2 === true,但NaN < 2 === false

因此,它确实不是一个有意义的表达。 [null, null] < 3false,因为"," < 3实质上是做NaN < 3

+0

非常感谢,我希望它是。我以空值为例,但字符串分割的结果总是包含字符串。 – 2012-03-21 22:15:30

+0

@Dimitar Christoff:确实;在数组 - >字符串 - >数字转换中唯一存在的数组是一个包含数字的单元素数组。例如。 '[2] <3 === true'。 – pimvdb 2012-03-22 08:37:49

2

使用<>运算符将数组与数字进行比较并不安全,可靠或正确。你不应该这样做。

下面是this O'Reilly book采取的转换规则:

这些比较操作符的操作数可以是任何类型的。 只能对数字和字符串进行比较,但是,因此 不是数字或字符串的操作数被转换。比较和 转换发生如下:

如果两个操作数都是数字,或者两者都转换为数字,则它们是数字比较的 。

如果两个操作数都是字符串或转换为字符串,则将它们作为字符串进行比较 。

如果一个操作数是或转换为一个字符串,另一个是或转换为 号码,则操作员会尝试将该字符串转换为数字,然后执行数字比较。如果该字符串不代表 号码,则它将转换为NaN,并且比较结果为false。 (在 的JavaScript 1.1中,字符串到数字转换导致错误 而不是产生的NaN的。)

如果一个对象可以被转换为一个数字或字符串, 的JavaScript进行数值化。这意味着,例如, Date对象进行数值比较,它是有意义的 比较两个日期,以查看一个是否比另一个早。

如果比较运算符的操作数不能同时被 成功转换为数字或字符串,这些运算符 总是返回false。

如果任一操作数为或转换为NaN,比较运算符 总是产生错误。

在这种特殊情况下,由于没有将数组转换为数字,因此最终会比较两个完全不可靠的字符串。

这是你只应该比较两个相同类型的项目的另一个原因。在这种特殊情况下,它也很多,更可读的代码直接使用.length性能及用途:

a.length > 2 
+0

'数组'没有'toNumber',当转换为数字时,数组是'NaN'。 – 2012-03-21 22:01:09

+0

是的,在我的港口我只是这样做,长度。我已经为此提交了一张票,有人试图说服我确实没问题,所以我认为我错过了某种强制手段。谢谢! – 2012-03-21 22:19:32

2

我得到它不是安全的感觉,这是因为:

[0, 0] > 1 // false 

[0, 0] < Infinity // false 

好吧,它根本没有比较元素的数量。它比较数组的字符串表示形式,因此NaN < Infinity给出false。所以答案是否定的,这完全不是一个安全的选择,因为它们不是远程执行相同的事情。它仅适用于你,因为:

[null] < 2 -> null < 2 -> 0 < 2 -> true 

[null, null, null] < 2 -> ',,' < 2 -> NaN < 2 -> false 
+0

嘿,好抓。这将很好地处理我的情况。 – 2012-03-21 22:03:10

1

不能将数组转换为数字。这里发生的是数组正在转换为字符串。

当数组转换为字符串时,内部JavaScript确实是array.join(',')。因此,['a','b']变为"a,b"

[null]""[null,null]","。这是因为null被转换为空白字符串。

因此,[null,null] < 2"," < 2这是错误的。

要获得数组的长度,请使用.length

1

哦,它的安全,它只是没有比较你认为它的比较。

表达式parts < 2正在比较数组和数字。为了完成这个比较,JavaScript必须将这两个值转换为一个通用类型,唯一可用的是字符串。数组对象的toString()方法将数组元素的每个字符串值连接到一个逗号,并且null的字符串值是一个空字符串。所以你的测试表达式正在执行",," < "2""" < "2",我确定这不是我想要的。

只要你不在阵列上使用delete(改用slice),使用长度应该是完全安全的。