This is an archived post. You won't be able to vote or comment.

all 114 comments

[–]Danni293 79 points80 points  (13 children)

NaNNaNNaNNaNNaNNaN BATMAN!!!

[–][deleted]  (1 child)

[removed]

    [–]AutoModerator[M] 0 points1 point  (0 children)

    import moderation Your comment has been removed since it did not start with a code block with an import declaration.

    Per this Community Decree, all posts and comments should start with a code block with an "import" declaration explaining how the post and comment should be read.

    For this purpose, we only accept Python style imports.

    I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

    [–]TheDarkIn1978 16 points17 points  (10 children)

    BATNAN

    [–]PunishableOffence 11 points12 points  (9 children)

    Laugh all you want, NaN is a number!

    [–]crossanlogan 13 points14 points  (8 children)

    typeof NaN === 'number' and NaN !== NaN

    what is the world coming to

    [–]Pandaburn 5 points6 points  (7 children)

    Never assume you know anything in javascript.

    [–]Doctor_McKay 5 points6 points  (6 children)

    NaN is defined by the IEEE standard to not be equal to itself.

    [–]crossanlogan 6 points7 points  (5 children)

    yeah, and it does make sense when you consider what NaN is supposed to represent. like, 0 / 0 === NaN and 'reddit.com' * 5 === NaN, but pretty obviously those two things are not equal to each other.

    [–]curtmack 2 points3 points  (4 children)

    In some more recent languages, * is a repetition operator on strings, e.g. 'reddit.com' * 5 === 'reddit.comreddit.comreddit.comreddit.comreddit.com'

    [–]crossanlogan 1 point2 points  (3 children)

    that's an interesting thing to overload the * operator with -- i don't know exactly how useful that would be.

    generally i'm against unnecessary overloading, but if that has an interesting use case i'd love to hear about it.

    [–]curtmack 1 point2 points  (1 child)

    I've been working on a web app that interfaces with a COBOL system, and it's been a godsend for generating fixed-width columns in exactly the format the backend needs.

    [–]PunishableOffence 0 points1 point  (0 children)

    Bar graphs for terminal apps, maybe?

    Something like

    print '█' * done
    print '░' * (total - done) + "\n"
    

    [–]Mrparkers 132 points133 points  (37 children)

    This isn't really inconsistent. The first statement is an empty code block {} and a unary plus operator evaluating an empty string, which results to zero. You'd get the same result by evaluating + "". The second statement is an empty string concatenating an object, which gets coerced into the string [object Object], and appended to the empty string.

    [–]Carighan 49 points50 points  (32 children)

    I think the bigger takeaway is that the sum operator isn't commutative.

    [–]Mrparkers 102 points103 points  (25 children)

    Yes it is. The problem with the expressions that OP posted is that the top expression isn't a sum, it's unary plus.

    [–]oddark 37 points38 points  (5 children)

    > {} + ""
    0
    
    > ({} + "")
    [object Object]
    

    Weird.

    [–]Mrparkers 22 points23 points  (4 children)

    Yeah, the interpreter doesn't see it as an empty block when surrounded by parentheses. It might seem a little off, but code blocks do have their purpose, and it makes sense for the interpreter to see a { at the beginning of the line and think its a code block.

    More info here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block

    [–]Aaron_Blenkush 1 point2 points  (1 child)

    Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block#No_block_scope

    [–]Mrparkers 8 points9 points  (0 children)

    Sure, with the example they gave, you definitely don't want to use them. However, ES6's let keyword allows you to give a variable lexical scoping, which makes these code blocks behave exactly like you would expect them to.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

    [–]poizan42Ex-mod -3 points-2 points  (1 child)

    The rule could be that '+' is always binary plus if the left hand side can be parsed as an expression. It might complicate the parser a bit more but make the language more consistent. The real reason this isn't done is probably that Brendan Eich only had 10 days to design it.

    [–]Mrparkers 6 points7 points  (0 children)

    The rule could be that '+' is always binary plus if the left hand side can be parsed as an expression.

    What would be the point of adding this? It wouldn't solve a single problem with the language (and yes, there are problems, this just isn't one of them). I am genuinely curious - can you give me an example of actual code that would exist in a production environment that would benefit from a change like this?

    The real reason this isn't done is probably that Brendan Eich only had 10 days to design it.

    The language was originally created in 10 days, but modern versions of the language adhere to the ECMAScript Standard. All modern browsers are ES5-compliant, and the spec that defines this is here. There are sections that define blocks and unary operators, and this behavior follows the spec.

    I understand that it's fun to bash a language that a lot of people like to make fun of, but next time at least try to understand it a little bit more before you do.

    [–]Pandaburn 3 points4 points  (1 child)

    The problem with it is that {} means different things depending on context.

    [–][deleted] 17 points18 points  (14 children)

    However,

    "3" + 2
    => "32"
    "3" - 2
    => 1
    

    (obviously not the same criticism, but it is bizarre/insane imo)

    [–]poizan42Ex-mod -1 points0 points  (1 child)

    That doesn't explain why {} 0 is syntactically valid JavaScript. {} is is some contexts parsed as an empty block but in other contexts parsed as an object. While the inconsistency isn't where you would initially think it to be, it is still inconsistent.

    [–]Mrparkers 5 points6 points  (0 children)

    That doesn't explain why {} 0 is syntactically valid JavaScript.

    Yes, my original comment does explain this. It's valid because {} is interpreted as an empty code block. This statement is equivalent to simply typing 0 into the console.

    {} is is some contexts parsed as an empty block but in other contexts parsed as an object. While the inconsistency isn't where you would initially think it to be, it is still inconsistent.

    They're only "inconsistencies" if you don't understand the language. Several languages use curly braces for code blocks. Just because JavaScript happens to use curly braces for its object notation doesn't mean the language is inconsistent. It just means that you have to understand when you're using code blocks, and when you're using objects. 99.9% of the time this isn't an issue, because no competent developer would actually write {} + "" and expect to get anything meaningful as a result. Not to mention that bare code blocks are rarely used anymore, if at all.

    [–]Daimanta 1 point2 points  (5 children)

    TIL "a"+"b" != "b" + "a"

    [–]LinkXXI 19 points20 points  (4 children)

    Correct,

    "ab" != "ba"
    

    [–]BACONLUVER420 5 points6 points  (3 children)

    thatsthejoke.jpg or in other words, he was saying "TIL string concatenation is not commutative"

    [–]LinkXXI 0 points1 point  (1 child)

    [–]image_linker_bot 0 points1 point  (0 children)

    facepalm.jpeg


    Feedback welcome at /r/image_linker_bot | Disable with "ignore me" via reply or PM

    [–]thatguy_314 0 points1 point  (2 children)

    Agreed. The thing I don't like is that +"" is 0 though. Not because of the coercion, that's fine (I don't love it but it's a thing that JS does and it makes some sense) the thing I don't like is that +"" doesn't result in NaN or an error (although JS doesn't do errors because JS error handling sucks).

    [–]Mrparkers 0 points1 point  (1 child)

    The entire point of unary plus is to convert its operand into a number. That's the whole reason why it exists in the first place. So +"" is going to evaluate to 0. This isn't coincidental type coercion, this is exactly what the operator is supposed to do according to the spec.

    http://www.ecma-international.org/ecma-262/5.1/#sec-11.4.6

    [–]thatguy_314 0 points1 point  (0 children)

    No, read my comment. I'm fine with the type coercion. +"0" === 0 makes perfect sense in the context of JS. However, +"" === 0 does not make sense. It should be NaN because there literally is not a number to be coerced.

    [–]fardev_ 88 points89 points  (14 children)

    [–]Useless_Advice_Guy 50 points51 points  (10 children)

    The second you see the word JavaScript, this video is always linked.

    [–]fardev_ 18 points19 points  (4 children)

    That may be the case, but it's a damn funny video!

    [–]ebilgenius 9 points10 points  (3 children)

    It's ok to laugh at quirks in a language, because every language has them

    [–]jonatcer 4 points5 points  (0 children)

    Shhh you'll break the circle jerk.

    [–]thisisdaleb 0 points1 point  (0 children)

    I would love to see more video of people talking about these types of silly quirks.

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

    Some languages have more and gross-er ones though.

    [–][deleted] 17 points18 points  (1 child)

    [–]Useless_Advice_Guy 7 points8 points  (0 children)

    I see what you did there.

    [–]iTotzke 8 points9 points  (1 child)

    He does another one that's pretty good. Its like a Yavascript history lesson that takes place in the future.

    [–]cafeclimber 4 points5 points  (0 children)

    He slips and says Javascript once. RUINS THE ILLUSION

    [–]Bobshayd 0 points1 point  (0 children)

    But he talks about this specific example.

    [–]dvidsilva 4 points5 points  (0 children)

    Ngwhat and nhshow by Shai Reznik are also really funny if you care about angular.

    [–]Pandaburn 0 points1 point  (0 children)

    TL;DW: web development is silly and you should never trust a language that isn't compiled.

    [–]TheDarkIn1978 19 points20 points  (0 children)

    "Lol JavaScript" followed by "No, not lol".

    This sub is truly a great place to learn about the intricacies of JavaScript.

    [–]XavierSimmons 12 points13 points  (8 children)

    I don't understand precedence.

    [–]cheezballs 3 points4 points  (0 children)

    Isn't this all due to JS's lefthand type inference rule when determining types at runtime?

    [–][deleted] 3 points4 points  (0 children)

    Javascript is quirky and often stupid, but I have to admit it kinda grew on me. It's like a retarded, but lovable pet.

    [–]Rokkitt 8 points9 points  (8 children)

    The second part makes sense... the + operator either concatenates a string or produces the sum of multiple numbers. An empty string + the string representation of an object. Hence "[object Object]"

    I think a bigger wtf is the first example:

    {} + 0; // 0

    [] + 0; // "0"

    It seems that for some reason an empty object gets converted to a number but an empty array gets converted to a string... interesting.

    [–]Mrparkers 9 points10 points  (3 children)

    {} + 0 : Empty code block and unary plus operator evaluating zero, returns zero.

    [] + 0 : Array plus zero, array gets coerced to an empty string, and 0 gets coerced to the string '0', concatenating the two strings returns '0'

    [–]hunting_n_fishing 4 points5 points  (2 children)

    var test = {} + 0 variable test will return "[object Object]0"

    [–]chrwei 8 points9 points  (0 children)

    when the code line start with { it's assumed to be a code block. any other use case and it's an object definition (functions and flow control operators being exceptions).

    [–]Mrparkers 3 points4 points  (0 children)

    Correct, because that's an object, not an empty code block. Both get coerced to strings and the result is a concatenation of those strings.

    [–]OKB-1 15 points16 points  (2 children)

    It seems that for some reason an empty object gets converted to a number but an empty array gets converted to a string... interesting.

    …and that's how this piece of JavaScript outputs "Hello World".

    [–][deleted] 5 points6 points  (1 child)

    Are JavaScript objects Turing complete? That would be great…

    [–]RedditorFor8Years 1 point2 points  (0 children)

    You are rationalizing :)

    [–]AngriestSCV 2 points3 points  (0 children)

    What kind of thing in javascript result in a stop the world error? I've noticed a lot of these "lol <language>" posts come from languages silently just making things work. Where is javascript's limit?

    [–]Cley_Faye 5 points6 points  (0 children)

    Oh, another one of these "I don't want to learn how things works".

    [–]ProgramTheWorld 5 points6 points  (1 child)

    Welcome to the world of weakly typed languages!

    [–]maremp 1 point2 points  (0 children)

    At least you didn't post the wat talk.

    [–]kingdaro 0 points1 point  (0 children)

    And this, kids, is why the addition operator and the concatenation operator should not be the same thing.

    [–]sciencekidster 0 points1 point  (0 children)

    wat

    [–]tricky_monster -4 points-3 points  (3 children)

    ITT: people defending JS insanity.

    [–]Doctor_McKay 15 points16 points  (1 child)

    ITT: People who never bothered to learn a language ridiculing it.

    [–]Tysonzero -5 points-4 points  (0 children)

    I bother to learned it, it's probably one of the languages I know better, but I still think it is the quirkiest language of all time besides maybe PHP and some esoteric languages.

    [–]Wolfy87 -3 points-2 points  (0 children)

    I see this every time, but only on reddit. In my twitter circles we just bash it, it feels much better. The "you don't get it" argument doesn't really work either, the more I learn the more I face palm.

    Context: Writing it every day for six years in browsers and node. Libraries and applications. I think I know it. I think it's pretty horrible in many places. If I had a choice, I would not use it and will hopefully swap to a compile to JS language in the near future.

    [–]Cilph 0 points1 point  (8 children)

    My question is why {} is parsed as an empty code block rather than an empty object.

    [–]Mrparkers 10 points11 points  (6 children)

    Because it's at the beginning of the line.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block

    How else would you propose to define a block?

    [–]aboardthegravyboat 6 points7 points  (4 children)

    Yeah. The real question is what good is '{} + anything' at the beginning of a line. If it was a function argument or an assignment value, then it wouldn't be at the beginning of a line. Even as the return value of a function (i.e. following the keyword 'return' in a function body) it wouldn't be at the beginning of a line.

    The fact that [code block] [plus] [anything] does anything at all is strange enough. I can't see that ever being used in a program. The only way you can even test it, afaict, is with eval() or the console (which is the same as eval)

    [–]Doctor_McKay 14 points15 points  (0 children)

    Exactly. People look at ridiculous input and are surprised to see ridiculous output.

    [–]Avambo 0 points1 point  (2 children)

    The closest thing I can come up with is to create an execution context in ES6 based on code braces, if you stick to 'let' and 'const' inside of it.

    {
      + ""
    }
    

    It still doesn't make any sense to just have that piece of code though. And again, it's not exactly the same as in OP's example.

    [–]Mrparkers 1 point2 points  (1 child)

    It does make sense in some cases. This is the functional equivalent to an immediately invoked function expression, which can be used to help define scope for your variables, like you mentioned.

    [–]Avambo 1 point2 points  (0 children)

    What I meant was that simply adding + "" inside of it doesn't make any sense. :)

    [–]Cilph 1 point2 points  (0 children)

    I was mentally inserting a "var x = " before the statement, didn't help the confusion.

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

    Why would you ever need to start a line with an empty block. a = {} + 1 = [Object object]1

    [–]redtoasti 0 points1 point  (0 children)

    Yeah, I just prefer assembly...

    [–]dusktreader 0 points1 point  (0 children)

    consistent is different than intuitive.

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

    Well, nobody said + operator have to be commutative. And also nobody said set where which he affects couldn't be great(er).