On Github th507 / talk-javascript-parenthesis
by Jingwei Liu (@th507), Meituan.com
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 any statement can be prefixed by a label.
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 code block with a label and a statement inside.
// 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 = 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