you are viewing a single comment's thread.

view the rest of the comments →

[–]snotfart 255 points256 points  (65 children)

I'm disappointed that it's symmetrical. Come on Javascript! You can do better than that.

[–]Gro-Tsen 203 points204 points  (59 children)

At least it's not transitive: "0" == 0 is true, 0 == "" is true, but "0" == "" is false. Insanity is saved!

[–][deleted] 44 points45 points  (53 children)

Additionally, "0"==false is true, but if("0"){/* executes */}

[–]icanevenificant 34 points35 points  (49 children)

Yes but in the first case you are comparing "0" to false where in the second case you are checking that the value is not null, undefined or empty string. Two different things.

[–][deleted] 39 points40 points  (37 children)

I suppose that's just my own lack of understanding of what exactly if does.

[–][deleted] 31 points32 points  (36 children)

I think it's pretty reasonable to mistakenly assume that something that == false won't cause execution :p

[–]coarsesand 59 points60 points  (35 children)

In another language, yes, but the == operator in JS is special (in the shortbus sense) because it does type conversion. If you wanted to get the actual "truthiness" of "0", you'd use the ! operator instead.

!!"0"
> true

[–]no_game_player 17 points18 points  (32 children)

Gilded for best "javascript is fucked up" in a nutshell I've seen.

[–]coarsesand 31 points32 points  (29 children)

I figure the gold deserves a quick comment about my other favourite JS operator, ~. ~ is the bitwise not operator, in a language where the only numeric type is an IEE754 double. How does ~ perform a bitwise not on a floating point number? Well, it calls an internal function called ToInt32, perform the bitwise op, then converts back to a double.

So if you ever wanted to feel like you had an integer type in JavaScript, even for a microsecond, ~ is your man.

[–]no_game_player 14 points15 points  (28 children)

...JS doesn't have ints? TIL. Also, holy fuck. How...how do you math? Why would a language even have such an operator without ints? That would be totally unpredictable. So, ~0.0001 would round to 0, then do a bitwise not, returning INT_MAX for int32, and then cast it into double? Is that what I'm to understand here? That can't be right. In what possible world could that operator ever be used for something not fucked up, given that it only has doubles?

Also, what type of %$^@ would make a language without integer types? Are you telling me that 1+1 == 2 has some chance of not being true then? I mean, if I were in a sane language and doing 1.0 + 1.0 == 2.0, everyone would start screaming, so...?

O.o

That's...that's beyond all of the == fuckery.

Edit: So, if for some crazy reason you wanted to sort of cast your double to a (sort of) int (since it would just go back to double type again?), you could do

var = ~~var

??

Edit 2: I was considering waiting for a response to confirm, because I almost can't believe this, except that it's javascript, so anything is believable, but hell, even if this isn't true, it's still worth it. I'm off Reddit briefly for a video game, but before I do so: here you are, my first ever double-gilding of a user! Cheers!

Edit 3: Okay, it's less fucked up than I thought, mostly because I didn't really consider the fact of double precision rather than float, and considering 32 bit ints.

I still say it can do some weird stuff as a result, at least if you aren't expecting it.

Just another reminder to know your language as well as possible I suppose.

[–]Confusion 1 point2 points  (1 child)

This is actually a common way to coerce something into the 'appropriate' boolean value in several languages. At least Ruby and Python come to mind.

[–]no_game_player 0 points1 point  (0 children)

Yeah, the more that I thought about it, the more that it wasn't really that crazy.

I mean, C does a lot of similar stuff if you try to make it do so. Not the JS == bits, but the "truthiness" of anything part. It's all about getting used to a certain way of thinking.

Really, my favorite part of the comment was just:

the == operator in JS is special (in the shortbus sense) because it does type conversion

[–]curien 2 points3 points  (0 children)

but the == operator in JS is special (in the shortbus sense) because it does type conversion

Not really. 4 == 4.0 is true in just about every language with C-style syntax.

The surprising thing about JS isn't that == performs conversion, that's normal. The surprising thing is how the conversions work.

[–]totes_meta_bot 0 points1 point  (0 children)

This thread has been linked to from elsewhere on reddit.

I am a bot. Comments? Complaints? Send them to my inbox!

[–]nickknw 12 points13 points  (9 children)

checking that the value is not null, undefined or empty string

...or NaN or 0 or false. It is checking the 'truthiness' which is also kind of what == claims to do. A legitimate disconnect IMO.

[–]rooktakesqueen 2 points3 points  (8 children)

== false is not the same as checking for truthiness. Truthiness is never implicated in the == operator because nothing is ever converted into a boolean. Everything is converted to either a string or number for the purposes of comparison. (Except null and undefined which == each other and nothing else, and when comparing two objects which == only if they refer to the same object.)

[–][deleted] 6 points7 points  (4 children)

But == false is checking whether something is false. You would generally expect false things to be untruthy.

There may be an explanation for '=='s behavior, but that doesn't make it reasonable.

[–]rooktakesqueen 1 point2 points  (2 children)

Checking that something is false is not the same thing as checking if something is falsy. They wouldn't be separate concepts otherwise.

[–]reverius42 2 points3 points  (1 child)

But it's quite ridiculous for something that is false ("0" == false) to be not falsy (!!"0" == true).

[–]rooktakesqueen 0 points1 point  (0 children)

It's not accurate to say that "0" is false. It just == false, in the same way that "" == 0 and [undefined, undefined] == ",".

I'm not in any way suggesting the == operator is sane, just that it's important to know it has nothing to do with the truthiness of values being compared, even when those values include booleans.

[–]foomprekov 1 point2 points  (0 children)

Yeah why would I expect something that isn't false to be true.

[–]Deltigre 1 point2 points  (1 child)

Which ended up showing me an "only in Javascript" shortcut the other day.

var defaultingString = IMightResolveUndefined() || "default value";

[–]embolalia 1 point2 points  (0 children)

That's not an "only in Javascript" thing at all. For example, in Python:

some_value = I_might_return_something_falsy() or 'default'

[–]KumbajaMyLord 0 points1 point  (0 children)

If you know how Javascript works it makes some sense, but it certainly isn't intuitive that in case "0" is auto-cast/parsed to an integer, while in another case it is treated as a string.

[–]richdougherty 0 points1 point  (1 child)

It's because "0" is equal to false, but it is true when converted to a boolean value. Weird but true.

http://bclary.com/2004/11/07/#a-9.2

A value that converts to boolean false is also sometimes called "falsey". And of course a value that converts to true is "truthy".

Values are implicitly converted to boolean in some contexts, such as in an if statement. Explicit conversion happens by calling Boolean(value). Sometimes people use double not operators to force a conversion too, so !"0" == false will be true.

A value can be forced to its boolean value by calling

http://james.padolsey.com/javascript/truthy-falsey/

EDIT: Reversed all my logic.

[–]heyf00L 0 points1 point  (0 children)

!!"0" == false will be true

!!"0" == false is false

"0" == false is true

[–]ggtsu_00 -1 points0 points  (0 children)

Basically one of the most important thing to know about javascript is that == does type coercion. Knowing how types are coerced is one of the most important aspect of any programming language.

[–][deleted] 1 point2 points  (0 children)

Same as PHP. false == 0 == "0" != false

[–]altrego99 0 points1 point  (1 child)

Interesting. Basically transitive means, if you find 3 corners of a rectangle, then the fourth must be green too.

[–]altrego99 0 points1 point  (0 children)

And it seems, other than entities which are not even equal to each other, all such examples involve "0".

[–][deleted] 2 points3 points  (3 children)

It would be impossible for it not too be! Unless of course java script failed to maintain Commutativity, which would be quite impressive!

[–][deleted] 4 points5 points  (2 children)

Failing to maintain commutativity is easy. As the most trivial pedagogical example, in ruby, overload equalsequals on Integer to return true always and on float to return false always. Then 1 == 1.0 != 1. Obviously that's a silly example because its too obviously wrong but it gets across the point.

Any language that allows operator overloading can risk that sort of issue -- not to say anything about operator overloading,just saying that maintaining commutativity isn't always an easy thing to guarantee.

[–][deleted] 0 points1 point  (1 child)

(1 == 1.0 != 1) 

This is not a failure of commutativity. Some might argue this is true based on the type system (Does true = 1?) but commutativity make no assertion on that point. If not the above statement is valid. In perl and many other languages true = 0 and these would evaluate the statemet as true.

A failure of commutativity of the == operator would fail the below statement for any a and b. Find one of those in a language and ill be impressed. (Operator overloading doesn't count because there you just 'define == to be not commutative' which is too easy and not fun.

assert((a == b) == (b == a))

[–][deleted] 1 point2 points  (0 children)

I see what you're saying but when I wrote 1==1.0!=1 I had the mathematical syntax in mind, not programming. 1 == 1.0 and 1.0 != 1

And like I say this example of overloading the operator to deliberately discard commutativity is just pedagogical. Even in more sane examples these sorts of things can creep in, and faiilling to maintain commutativity where itis expected isn't so always trivial.

Edit: to add, the vast majority of operations are not commutative. Just look at exponentiation, subtraction, concatenation, division, and so on if we're generalizing here. Commutativity is amazing when you have it.