JavaScript edge cases


  • Plugin & Theme Dev

    I've recently come across an image showing some "mysterious" or "counter-intuitive" equations/command-results within JavaScript.

    The link I've been given is dead today, so I can't share it sadly.

    The one I most wondered about was

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

    The [] + {} is simple since [] gets stringified to an empty string and the stringified {} gets added.
    As it seems within {} + [] the + gets used as unary operator instead of binary with stringifying {} in first place, that's confusing.

    Since var x = {}; x + [], ({} + []), var x = {} + [] result in "[object Object]" I believe it's kind-of buggy interpretation.

    And since it's the same with {hello: "world"} + [] I think they handle it like {hello: "world"}; + [], so they treat the object as single expression...

    Does anybody else have a better explanation or a reason for this behavior?

    Also if you know nice edge cases, I'd like to hear about them 😉

    I also remember of

    • Math.min() > Math.max() which is pretty true if you think about it 😄
    • pretty neat: == is not transitive (=== for sure is)
    0 == "0"
    > true
    0 == ""
    > true
    "" == "0"
    > false
    

  • Community Rep

    I can't really answer your question, but this has come in handy: http://dorey.github.io/JavaScript-Equality-Table/unified/


  • GNU/Linux

    Oh yeah! I like this topic, already. Let's geek the **** out! :neckbeard: 😊

    I think it's important to mention, that I'm fiddling in Chrome. Which is always a good idea, when trying code for nodeJS. Both use V8. Safari, FireFox, etc. might behave differently!
    (0 == '') === true
    

    could be, because JS does type conversion there. I doubt that the function is internally used, but the underlying C might be the same, due to DRY. Anyway does

    (Number('') === 0)
    

    hold true. 🙂

    Your actual question startles me a bit, too. First fiddles make me think the same - implementation hickup.
    Because the objects seem the same

    Object.getOwnPropertyNames([]+{})
    ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "length"]
    Object.getOwnPropertyNames({}+[])
    ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "length"]
    

    They seem to be both strings

    typeof ({}+[])
    "string"
    typeof ([]+{})
    "string"
    

    I just love how Array() doesn't allocate, but makes you believe it has:

    Object.keys(new Array(7))
    []
    new Array(7).length
    7
    Object.keys(Array.apply(null, { length: 7 }))
    ["0", "1", "2", "3", "4", "5", "6"]
    

    😵



  • have a look at this short talk: https://www.destroyallsoftware.com/talks/wat


  • GNU/Linux

    WATMAN!

    😑 -> 😖 ->😂 😂 😂

    I like to point out, though, that almost everything in JavaScript is an Object; so are Arrays. Arrays are simple Objects with Integer keys and a length property. That's why [] + {} is not a TypeError. 😉

    I guess I'll be reading up on + now, though. ^_^

    P.S. Gotta love fail talks! 🙂


  • Plugin & Theme Dev

    @belstgut said:

    have a look at this short talk: https://www.destroyallsoftware.com/talks/wat

    Great one 😄

    @rbeer said:

    I think it's important to mention, that I'm fiddling in Chrome. Which is always a good idea, when trying code for nodeJS. Both use V8. Safari, FireFox, etc. might behave differently!

    DITO, just replace Chrome with Chromium for me.

    @rbeer said:

    Your actual question startles me a bit, too. First fiddles make me think the same - implementation hickup.
    Because the objects seem the same

    Object.getOwnPropertyNames([]+{})
    ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "length"]
    Object.getOwnPropertyNames({}+[])
    ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "length"]
    

    They seem to be both strings

    typeof ({}+[])
    "string"
    typeof ([]+{})
    "string"
    

    yes, they're both strings. they're both the same string namely "[object Object]". But that's only the case for {} + [] as long you use it in any context such as ({} + []) === "[object Object]".
    So the "weird behavior" only occurs if {} + [] is the full statement (or at least there is NOTHING in front of this, not even braces).


  • Plugin & Theme Dev

    The {} + {} > NaN mentioned within the video is actually the same like {} + [], the + gets interpreted unary and the leading {} gets ignored and + {} for sure is NaN.
    In contrast ({} + {}) === "[object Object][object Object]" as you'd expect {} + {} to be too.


  • Plugin & Theme Dev

    I found out what exactly does reason this behavior:

    Consider the full statement {}.
    The result is undefined.

    Consider the full statement {hello: "world"}.
    The result is "world". - Same result with the full statement hello: "world"

    Consider the full statement {hello: "world", hey: "frissdiegurke"}
    => SyntaxError

    So it looks like objects within those statements but those in fact get interpreted as code-blocks.
    So within {} + [] this is what happens (according to me):

    1. {} gets validated as code-block
    2. a semicolon gets inserted by static code-analysis according to ECMAScript Rule 11.9.1 because + ain't valid behind a code-block.
    3. {}; gets executed (expression returns undefined, gets ignored).
    4. + [] gets executed and returns 0

    Since I can't find any rule that forces code-block interpretation in that case I think {hello: "world", hey: "fdg"} should get interpreted as object once code-semantics fail instead of throwing SyntaxError.

    But in fact Gary Bernhardt is not doing what he's saying "an object plus an object is actually not a number" while executing {} + {} xD 😛


  • GNU/Linux

    Duh! Of course! That annoying ;-insertion. Nicely done!

    semi: [2, "always"] 😉


Log in to reply
 

Suggested Topics

  • 17
  • 1
  • 3
  • 21
  • 5
| |