admin管理员组

文章数量:1323735

this had me surprised:

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

reference: .mailcheck.js#L21-22

essentially, it looks like:

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

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

so it seems like it works but I want to know why, what coercion actually happens for it to do this? as the intent here was to bail if less than 2 parts e from the email string, i would have expected it to always pass due to the array defined being truthy - it ought to create an array with at least 1 member even on an empty string.

i would always prefer to use array.length. is the above safe?

this had me surprised:

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

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

essentially, it looks like:

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

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

so it seems like it works but I want to know why, what coercion actually happens for it to do this? as the intent here was to bail if less than 2 parts e from the email string, i would have expected it to always pass due to the array defined being truthy - it ought to create an array with at least 1 member even on an empty string.

i would always prefer to use array.length. is the above safe?

Share Improve this question edited Mar 21, 2012 at 22:17 Dimitar Christoff asked Mar 21, 2012 at 21:55 Dimitar ChristoffDimitar Christoff 26.2k8 gold badges51 silver badges69 bronze badges 8
  • 1 Well, array.length isn't always safe either considering that it doesn't always readjust when an element is deleted ;) – Jeffrey Sweeney Commented Mar 21, 2012 at 21:59
  • 1 @JeffreySweeney - .length always represents the actual length of the array. If an element is removed with something like .splice() or .pop(), then .length will immediately and reliably return the new length. If you merely set an array element to undefined, that array element still exists and all the other array elements stay in their same locations so the .length value correctly does not change. Can you describe when you think .length is not accurate. – jfriend00 Commented Mar 21, 2012 at 22:18
  • thanks for the replies, sanity check done, issue filed, i am not going insane... – Dimitar Christoff Commented Mar 21, 2012 at 22:22
  • @jfriend00 deleting elements at the end of the array will not adjust the length property (perhaps intentionally), and there has been browser discrepancies in the past (hexmen./blog/2006/12/push-and-pop). In addition, it is way too easy to change the property itself, and a fallacious framework or lazy programmer can cause a lot of confusion. – Jeffrey Sweeney Commented Mar 21, 2012 at 22:28
  • @JeffreySweeney - you make no sense. So, how do you even propose to use an array if you don't use the .length property? And, what do you remend the OP do to solve their question. – jfriend00 Commented Mar 21, 2012 at 22:31
 |  Show 3 more ments

5 Answers 5

Reset to default 4

It's a string and then number conversion that's happening, since arrays can't be directy pared with the < operator. First it will do a string parison but with the number it will then do a number parsion.

Note that:

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

And:

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

Now it makes sense because 0 < 2 === true but NaN < 2 === false.

It's therefore not a meaningful expression indeed. [null, null] < 3 is false because "," < 3 is essentially doing NaN < 3.

I get the feeling that it's not safe, because:

[0, 0] > 1 // false

and

[0, 0] < Infinity // false

Okay, it's not paring the number of elements at all. It pares the string representation of the array, hence NaN < Infinity giving false. So the answer is no, it's not at all a safe alternative because they don't do remotely the same thing. It only works for you because:

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

but

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

Using the < or > operators to pare an array to a number is not safe, reliable or correct. You should not do it.

Here are the conversion rules taken from this O'Reilly book:

The operands of these parison operators may be of any type. Comparison can be performed only on numbers and strings, however, so operands that are not numbers or strings are converted. Comparison and conversion occur as follows:

If both operands are numbers, or if both convert to numbers, they are pared numerically.

If both operands are strings or convert to strings, they are pared as strings.

If one operand is or converts to a string and one is or converts to a number, the operator attempts to convert the string to a number and perform a numerical parison. If the string does not represent a number, it converts to NaN, and the parison is false. (In JavaScript 1.1, the string-to-number conversion causes an error instead of yielding NaN.)

If an object can be converted to either a number or a string, JavaScript performs the numerical conversion. This means, for example, that Date objects are pared numerically, and it is meaningful to pare two dates to see whether one is earlier than the other.

If the operands of the parison operators cannot both be successfully converted to numbers or to strings, these operators always return false.

If either operand is or converts to NaN, the parison operator always yields false.

In this particular case, since there is no conversion of an array to a number, it ends up paring two strings which is pletely unreliable.

This is yet another reason why you should only pare two items of the same type. In this particular case, it's also much, much more readable code to use the .length property directly and use:

a.length > 2

Arrays cannot be converted to numbers. What's happening here is the arrays are being converted to strings.

When arrays are converted to strings, internally JavaScript does array.join(',').

So, ['a','b'] bees "a,b".

[null] is "" and [null,null] is ",". This is because null is converted to a blank string.

So, [null,null] < 2 is "," < 2 which is false.

To get an array's length, use .length.

Oh, its safe, it's just not paring what you think its paring.

The expression parts < 2 is paring an array to a number. To plete this parison, JavaScript must convert these two values to a mon type, and the only one available is string. The toString() method of the array object concatenates each of the string values of the arrays elements w/ a ma, and the string value of null is an empty string. So your test expressions are performing ",," < "2" and "" < "2", which I'm certain isn't what's intended.

As long as you don't use delete on the array (use slice, instead), using length should be perfectly safe.

本文标签: javascriptweird arraylength alternative syntaxStack Overflow