Ответ 1
Разница для {} + []
заключается в том, что когда вы выполняете присваивание, она анализируется в контексте выражения, но когда вы вводите ее сама по себе, она анализируется как оператор
var b = /*an expression*/
Это различие видно при использовании анонимных функций
//expression
var f = function(){}; //allowed
//statement
function(){}; //not allowed. function statements need a name.
Итак, в контексте выражения мы добавляем {}
(пустой объект) и []
(пустой список) с двоичный +
оператор. Из-за правила преобразования типов, {}
преобразуется в строку "[object Object]" и []
преобразуется в пустую строку, конкатенацией которой является "[object Object]" тоже.
//parenthesis force an expression
({} + "hello") //"[object Object]hello"
({} + []) //"[object Object]"
({} + [1]) //"[object Object]1"
({} + [1,2]) //"[object Object]1,2"
Между тем, когда мы удаляем скобки, {}
анализируется как пустой оператор блока. В практических целях он работает так, как будто мы полностью его совершили, оставив унарный +
оператор, чтобы действовать в списке. Это преобразует его в число.
+[] // 0
{} + [] // 0
+{} // NaN
{} + {} // NaN
{} +"17"// 17
Хотя может показаться странным, что можно получить значение из оператора (а не только из выражений), стандарт Javascript, указать значение для оператора. В нашем случае наша программа представляет собой список из двух исходных элементов, значение задается последним оператором, a выражение выражения.
Способ увидеть значение завершения операции в действии - через eval:
eval("{}") //undefined
eval("1") //1
eval("1;2") //2