Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object coercion in js starting with block statement

Tags:

javascript

So, there is one thing I can't get my head around.

I have no problem understanding that:

{}+[]+{}+[1]

gives

"0[object Object]1"

What I really don't get though is why

{}+[]+{}

gives

"[object Object][object Object]" and not "0[object Object]"

My understanding is that the first {} is a block statement and thus is ignored. We then do have +[]+{} which results in "0[object Object]"

What am I missing here ?

EDIT: Despite being about the same subject, the other question isn't mentioning the difference between a {} being interpreted by the console as a block code or as an object.

like image 872
Scipion Avatar asked Apr 11 '19 09:04

Scipion


People also ask

What are the types of coercion in JS?

JavaScript has two characterized forms of coercion: implicit coercion and explicit coercion.

What is explicit type coercion in JavaScript?

There are two types of coercion in JavaScript: Implicit Coercion: Type conversion is done implicitly by JavaScript. Explicit Coercion: Type conversion is done explicitly in code using the inbuilt functions like Number(), String(), Boolean(), etc.

Which operator stops type coercion in JavaScript?

One operator that does not trigger implicit type coercion is === , which is called the strict equality operator.

Why do we need type coercion?

Type coercion is the automatic or implicit conversion of values from one data type to another. For example, converting a string value to an equivalent number value. It is also known as type conversion. Type coercion can be useful but it can cause inconsistencies.


1 Answers

It depends in which syntactic position the parser is when you evaluate your expressions. Consider:

console.log(eval('{}+[]'), '==', eval('{}; +[]'))
console.log({}+[])

console.log('---')

console.log(eval('{}+[]+{}+[1]'), '==', eval('{}; +[] + {} + [1]'))
console.log({}+[]+{}+[1])

console.log('---')

console.log(eval('{}+[]+{}'), '==', eval('{}; +[] + {}'))
console.log({}+[]+{})

where "eval" blocks correspond to the "statement" position and bare "console.logs" are in the "expression" position. The leading {} is only treated as a block in the statement position.

> let esprima = require('esprima');
undefined

> esprima.parse('{}+[]+{}')
Script {
  type: 'Program',
  body:
   [ BlockStatement { type: 'BlockStatement', body: [] },
     ExpressionStatement { type: 'ExpressionStatement', expression: [BinaryExpression] } ],
  sourceType: 'script' }

> esprima.parse('( {}+[]+{} )')
Script {
  type: 'Program',
  body:
   [ ExpressionStatement { type: 'ExpressionStatement', expression: [BinaryExpression] } ],
  sourceType: 'script' }
> 

Note that when you evaluate your tests directly in the console or repl, the behaviour may differ from platform to platform, because consoles/repls use different heuristics to decide whether your input is a statement or an expression. See this answer for examples.

like image 176
georg Avatar answered Oct 19 '22 15:10

georg