JavaScript edge cases
-
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 prettytrue
if you think about it- pretty neat:
==
is not transitive (===
for sure is)
0 == "0" > true 0 == "" > true "" == "0" > false
-
I can't really answer your question, but this has come in handy: http://dorey.github.io/JavaScript-Equality-Table/unified/
-
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 sameObject.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
-
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!
-
@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 sameObject.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). -
The
{} + {}
>NaN
mentioned within the video is actually the same like{} + []
, the+
gets interpreted unary and the leading{}
gets ignored and+ {}
for sure isNaN
.
In contrast({} + {}) === "[object Object][object Object]"
as you'd expect{} + {}
to be too. -
I found out what exactly does reason this behavior:
Consider the full statement
{}
.
The result isundefined
.Consider the full statement
{hello: "world"}
.
The result is"world"
. - Same result with the full statementhello: "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):{}
gets validated as code-block- a semicolon gets inserted by static code-analysis according to ECMAScript Rule 11.9.1 because
+
ain't valid behind a code-block. {};
gets executed (expression returnsundefined
, gets ignored).+ []
gets executed and returns0
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 throwingSyntaxError
.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