> [] + []
"" (An empty string)
> {} + []
0 (The number zero)
> [] + {}
"[object Object]" (.toString() called on a plain object).
> ![]
false (!{} is the same)
> !![]
true (not false)
> +[]
0 (the number zero)
> -[]
-0 (negative zero)
> +{}
NaN (Not a number, same goes for -{})
> "" + []
"" (empty string)
> "" - []
0 (number zero, not empty string)
And the one that gets more people than the previous list:
> typeof [] === typeof {}
true
Incidentally, some of these things can be useful. For example, +(x) will always evaluate to a double (unless it is preceded by a string), while (x|0) will always evaluate to a 32bit integer. asm.js abuses (to an extent) this to have more control over types, and most JavaScript engines would now store the result of (x|0) as an integer internally instead of a double.
Should you be using any of this in production code? No
The next programmer even if he is a really good one might not know that particular esoteric trick.
I'm not trying to vote down or anything, but what is the point? Most of it look like language design warts to me. Most of them should have thrown exceptions and errored out.
Now I'm loving the idea of static typing a lot more.
The bit at the end (integer and float casting) is almost essential knowledge now for anyone writing JavaScript code that does anything mildly intensive.
Yes it does, it makes sure you never do this ;P
Adding arrays sounds like something I'd totally try in JS, had I not known that it causes magic unicorn sparkles to happen)
> {} + [] > 0 (The number zero)
This is wrong, it is only true in the weird scenario that you type it into the jsconsole and don't use the result. It parses as an empty block ({}) and then an unrelated unary +[] after that. var x = {} + []; gives you a string and it is the same as var x = [] + {}.
There is more logic than it seems here:
Unary plus:
> always gives a number (a double: NaN is a double)
> on array: +a -> if len>=2: NaN else +a[0] (recursively)
> on object: NaN
> on string: parseNumber, or NaN if that fails
> on bool: 0 for false, 1 for true
> on null: 0
> on undefined: NaN
binary plus (addition):
> order doesn't matter except for the jsconsole pseudo-bug
> if both sides are number or boolean, add them
> else, toString() both sides and concat them
boolean negate (not):
> false for 0, false, "", null, undefined
> true otherwise
binary - (subtraction)
> x-y coerces x and y to number and subtracts them.
> Most mainstream languages that use + for string concat don't use - for some sort of string unconcat so its not too crazy.
> typeof [] === typeof {}
This isn't so crazy, typeof any non-primitive gives you "object".
[] is pretty much just an object plus magic .length property,
var x = []; x.blah = 7; console.log(x.blah) works. It doesn't work on number or bool. "$$$" = "["
"$$;" = "]"
"$;$" = "("
"$;;" = ")"
";$$" = "+"
";$;" = "!"Amazing that a simple alert("Hello world!") expands to over 16KB.
alert(1)
will produce 1227 chars while alert(1);
will produce 9535 chars. Interesting.I'd imagine that if you were serious about this, you'd implement, say, e=String.fromCharCode (12k chars) and use that to dig yourself out of a lot of this expensive stuff if you need more than one hard-to-encode character.
One interesting question was about the "performance impact"? One reply was: "Vanilla I got 225k ops/sec. JSFuck, 4.5 ops/sec. So about 50000 times slower."