Odd behaviour of comparison of object literals

后端 未结 4 1529
有刺的猬
有刺的猬 2020-12-10 22:24

I have searched but could not find logic behind following in JavaScript.

When I type in the Chrome console:

{} == null 

it returns

相关标签:
4条回答
  • 2020-12-10 22:29

    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.

    0 讨论(0)
  • 2020-12-10 22:37

    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.

    0 讨论(0)
  • 2020-12-10 22:38

    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;
    }
    
    0 讨论(0)
  • 2020-12-10 22:52

    You can find this in the specs under Statement (art. 12)

    12 - Statement

    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

    12.4 Expression Statement

    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).

    0 讨论(0)
提交回复
热议问题