I have searched but could not find logic behind following in JavaScript.
When I type in the Chrome console:
{} == null
it returns
It’s because JavaScript sucks The reason it doesn’t work is because JavaScript takes the type the comparison is taking from the first object.
For instance
3+”1” = 4
But
“3”+1 = 31
The first example does the operation as a number because the first object is a number The second example sees a string as the first object and treats the operation as concatenation of a string.
For your example {} is an object but null can’t be converted to an object
It works the other way because {} can be represented as a null object.
I would say this is a parsing issue, rather than a logic issue per se.
In Chrome I get the observed behavior.
In IE I get syntax errors whenever I put {}
(or, it seems, any object literal) on the LHS of the ==
.
In both browsers, putting ()
around the expression fixed things. Or first assigning the object to a variable
var x = {}
x == null
I would say it seems to me like a bug in the parsing. Whether that is true in an academic sense would take digging through specs and grammars; the practical answer is, there are simple enough work-arounds that the best bet is to not do that.
I assume you understand why {} == null
throws SyntaxError
. Long story short it is because {
in the begining starting a block statement not an object literal. You could check the answer here
As of why {} == {}
this works.
If you check chromium code that evaluates expressions in console. You could find the following (code)
if (/^\s*\{/.test(text) && /\}\s*$/.test(text))
text = '(' + text + ')';
executionContext.evaluate(text, "console", !!useCommandLineAPI, false, false, true, printResult);
This code wraps {} == {}
code with parentheses making it a valid expression ({} == {})
comparing two empty object literals. Which evaluates to false
because objects are compared by reference.
Node repl has the same behaviour src
if (/^\s*\{/.test(code) && /\}\s*$/.test(code)) {
// It's confusing for `{ a : 1 }` to be interpreted as a block
// statement rather than an object literal. So, we first try
// to wrap it in parentheses, so that it will be interpreted as
// an expression.
code = `(${code.trim()})\n`;
wrappedCmd = true;
}
You can find this in the specs under Statement (art. 12)
Statement :
Block.
VariableStatement
EmptyStatement
ExpressionStatement
.
.
.
The first applicable rules are either Block or Expression Statement. So we need to look at 12.4.
In 12.4 the specs clearly state that an expression statement cannot start with a {
.
though i haven’t yet found what makes example 2 an expression, maybe it’s implementation specific
Syntax ExpressionStatement : [lookahead ∉ {{, function}] Expression ;
NOTE An ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block. Also, an ExpressionStatement cannot start with the function keyword because that might make it ambiguous with a FunctionDeclaration.
Semantics The production ExpressionStatement : [lookahead ∉ {{, function}]Expression; is evaluated as follows:
Let exprRef be the result of evaluating Expression. Return (normal, GetValue(exprRef), empty).