by Jingwei Liu (@th507), Meituan.com
[] + [] = ?
[] + {} = ?
[] + [] = ""
[] + {} = "[object Object]"
[] + {}
= [].valueOf() + {}.valueOf()
Number, String, Boolean, undefined, null
typecast operands before evaluation
// typecast obj to boolean
!!obj
var arr = [];
// still not a primitive value
arr.valueOf() === arr;
[] + {}
// trying to get primitive value by valueOf
= ([]).valueOf() + ({}).valueOf()
// previous attempt fails, trying typecast instead
= ([]).toString() + ({}).toString()
= "" + "[object Object]"
= "[object Object]"
[] + {valueOf: function valueOf() { return 2}}
[] + {valueOf: function valueOf() { return 2}}
= "" + {valueOf: function valueOf() { return 2}}.valueOf()
= "" + 2
= "2"
{valueOf: function valueOf() { return 2}} + {valueOf: function valueOf() { return 2}}
{valueOf: function valueOf() { return 2}} + {valueOf: function valueOf() { return 2}}
= 2
{ StatementList }
Return the result of evaluating StatementList.
var a = 1, b = 2;
{a = 2; b = 3};
console.log(a, b);
// this is OK
[].toString();
// this will throw an error
{}.hasOwnProperty();
// this is OK. Wait, what?
{}hasOwnProperty();
The leading {} is treated as a code block in browsers.
{}.hasOwnProperty();
// equals to
.hasOwnProperty();
{}hasOwnProperty();
// equals to
hasOwnProperty();
// Chrome has an window.hasOwnProperty :)
// There are many ways to fool the browser
// so that {} won't be treated as a block
// wrap it in ()
({}).hasOwnProperty();
// add something in front of {}
"",{}.hasProperty();
Compression tools "fix" this for us.
A statement may be prefixed by a label.
Labelled statements are only used in conjunction with labelled break and continue statements.
loop: for (var i = 0; i < 1000; i++) {
if (i === 233) break loop;
}
// i = 233
console.log(i);
Almost
pointless: var a = 1;
Label doesn't do anything in this case.
{} + []
// processing code block
= +[]
// trying to get primitive value
= + [].valueOf()
= + [].toString()
= + ""
// typecast
= Number("")
= 0
{valueOf: function valueOf() { return 2}} + {valueOf: function valueOf() { return 2}}
The first part is treated as a
// This first part
{valueOf: function valueOf() { return 2}}
// { label: statement }
// label: "valueOf"
// statement: function valueOf() { return 2}
It doesn't return anything.
{valueOf: function valueOf() { return 2}} + {valueOf: function valueOf() { return 2}}
The second part is an object with a customized valueOf
method.
The answer is +2 =
{} + [] = +[] = 0 // in browser, not Node.js
{} + {} = +{} = NaN
{} + new Date = 1393349722245
[] + new Date = "Wed Feb 26 2014 01:35:28 GMT+0800 (KRAT)"
[] + + new Date = 1393349722245