{} + {} "[object Object][object Object]"

The Object Conversion: toString and valueOf in the Totals section describe the object behavior ( {} ) in the main code flow, but the behavior in the console is different. I even saw a similar example somewhere: {} + {} . It said that the left operand is considered as an empty “code block”, and the right one is counted to a number, the result of which will be NaN .

For one thing I wanted to ask how the parser sees this example: {} - {} .

  1. The parser ignores the left object and sees it as a "code block". Then the question arises, why does concatenation occur in the example above?
  2. He leads them to the number (NaN) and subtracts.

enter image description here

PS: I would know English and know ECMAScript documentation well, I would not ask.

2 answers 2

The main flow of code is a place that is not part of an expression.

Here are language moments that can only be placed in the main code flow:

  • function declaration (different from function expression)
  • code block (different from object)
  • labels (different from property names)
  • all syntactic constructions of the language: if, else, try, var, etc.

If there are two similar constructions, one of which can exist only in the main thread, then this criterion will be used to distinguish them: if the code is located in the main code flow, then the corresponding construction is chosen, and if in the expression, the other.

As for the {}+{} record, in the case of the main code flow, its value usually doesn’t go anywhere at all, although it is displayed in REPL environments as a result. The first brace means the opening of a block of code, then the second ends it. Then comes a plus - we have no left operand, which means it is unary. We are already in expression. A curly brace in an expression starts an object. Next - ends the object. It turns out +{} , then +"[object Object]" and NaN .

In the case of console.log , the function call itself forms an expression. Therefore, the first pair of parentheses turns into an object, and the entire sum after casting types into string concatenation.

The only way (at least in ES2018-) to get in the code is to pass a string with the code in eval.

 function run(code) { try { console.log(eval(code)) } catch(e) { console.log(e.name + " " + e.message) } } run('{console.log("I am the code block")} + {i:0, am:1, an:2, object:3}') run('({a:0, pair:1} + {of:2, objects:3})') // круглые скобки run('{not_object:0} + {object:1}') // метка! run('{not_object:0, really_not:1} + {object:2}') // ошибка - метка не может быть вне основного потока run('{not_object:0; really_not:1} + {object:1}') // `;`, а не `,` - две метки 

As for the chrome console - apparently they made a clever definition of whether something in curly braces is an object or a piece of code. Moreover, preference is given to the object. I think this is done for greater convenience, that if you enter an expression into the console, then you want the result of an expression that you will not get in the main code stream. But it is worth noting that this thing in the console only works for top-level-code (and even then not always), and does not apply to the embedded code:

screenshot of chrome console

  • correct the line ...то авыбирается соответствующая конструкция, а если в выражении, то другая. . If I understand you correctly, what I brought out the console was done for convenience, because in the main code flow it is пустой блок когда . I also wanted to ask about the comment: {not_object: 0} // Комментарий , and premises {not_object:0} in {} . For example, the operator () groups an expression and {} + {} becomes an expression (I apologize for tautology), and {} is similar in idea to the usual code flow, and works the same way, but the dissonance is that the code flow itself works differently типо для удобства )) - Acne Black
  • one
    @ Vitaly Black, I suppose that the logic is something like this: the comment is split up as forcing a statement instead of expression, since the comment is not part of expression. Parentheses clearly indicate expression, and curly brackets are just a block of code. Their expression chip works only on the same level - the top one - as soon as nesting appears, parsing follows the normal rules. - Qwertiy
  • I caught the main point, but my knowledge of the work of the parser is scarce, as well as the work of the code block. I would appreciate it if you look at my question and help me answer it. Question - Acne Black
  • PS: If it is not difficult, you can more simply or rephrase your comment: Их фишка с выражением работает только на одном уровне - верхнем - как только появляется вложенность, идёт парсинг по нормальным правилам. - Acne Black
  • A top-level code is a code located outside of any functions or blocks of code directly in the script. In principle, the same can be said about the console (although there is a slightly different situation, but you don't write any wrappers yourself). Apparently, they assumed that either the user entered some expression, or a piece of code. And if there are reasons to believe that this is not an expression (comment), or the user has clearly started a block of code, then everything goes according to the js rules. And if it looks like expression, then it is as if it would assign the result to a variable. - Qwertiy

Cast If it can to numbers leads to numbers.

If it cannot, it results in a string, {} + {}, causes a cast to a string, a concatenation of 2 strings.

When subtracting it is assumed that both operands are numbers, the conversion does not occur returns NaN

  • First, partly wrong. And secondly, the question is not about that. - Qwertiy
  • very reasoned of course - Azamat Galiyev