admin管理员组

文章数量:1195770

I was expecting JavaScript to reject objects with duplicated properties as invalid but it accepts them in some cases.

{"a":4,"a":5} results in an SyntaxError at least in Firefox and Chrome which seems obvious due to the property a being defined twice.

However ({"a":4,"a":5}) evaluates just fine and results in an object {"a":5} in both Firefox and Chrome.

Why is the expression with the parenthesis accepted?

Summing up the responses: The first example is simply not the construction of an object but a block of labeled statements. Duplicated properities in objects are perfectly valid in which case the last definition wins.

Thanks a lot for your answers!

I was expecting JavaScript to reject objects with duplicated properties as invalid but it accepts them in some cases.

{"a":4,"a":5} results in an SyntaxError at least in Firefox and Chrome which seems obvious due to the property a being defined twice.

However ({"a":4,"a":5}) evaluates just fine and results in an object {"a":5} in both Firefox and Chrome.

Why is the expression with the parenthesis accepted?

Summing up the responses: The first example is simply not the construction of an object but a block of labeled statements. Duplicated properities in objects are perfectly valid in which case the last definition wins.

Thanks a lot for your answers!

Share Improve this question edited Nov 8, 2012 at 11:23 Augustus Kling asked Nov 8, 2012 at 9:26 Augustus KlingAugustus Kling 3,3331 gold badge23 silver badges25 bronze badges 3
  • 1 Seems to work fine with and without parenthesis on FF and Chrome jsbin.com/iponud/1/edit. By fine I mean it returns the last a – elclanrs Commented Nov 8, 2012 at 9:33
  • @elclanrs: that result is misleading (I fell for it myself on jsfiddle earlier :) - placing the code in question inside of a console.log argument list removes the syntactic ambiguity that was causing the error in the first place – Oleg Commented Nov 8, 2012 at 11:38
  • Can you give an code example of when SyntaxError is thrown? I can't get it to throw in any circumstance. – Zamicol Commented Sep 13, 2022 at 16:55
Add a comment  | 

6 Answers 6

Reset to default 5

It is perfectly legal in ECMAScript 3 to declare duplicate properties in an object literal; the SyntaxError you get probably comes from the fact that you used an object literal as a statement, which is not possible due to the confusion with block statements ({ doSomething(); }).

If you want this to be reported as an error, you may want to switch to ECMAScript 5's strict mode: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode.

What you state has no problem if you assign it to a variable, if you don't however, you get the error you mention. Which makes all the difference from a syntax point of view.

When you wrap any structure in parens you are causing that syntax to be evaluated as an expression, the result of which is stored as a temporary variable. The error I get when not doing so in Firefox is unexpected label or invalid label, so it seems without assignment, or parens, this object construction is not treated as an object construction - instead it is treated as a block with multiple label statements that are defined illegally:

{
  a: function(){
    alert('a');
  },
  b: function(){
    alert('b');
  }
}

The above should be totally acceptable as an object, however you get a similar error if you evaluate it without assinging it to some form of variable, or evaluating it with parens. Put simply the duplication of the attribute name is not causing the error :)

Basically imagine your first example, but like this:

function (){
  "a": 4,
  "b": 5
}

That is roughly how these browsers are treating it, which is now obviously illegal javascript syntax... whereas it wasn't so obvious before.

In the first notation (parentheses-less) the javascript syntax is ambiguous. From ecmascript specification:

An ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block.

A block basically evaluates all the statements inside, equivalent to evaluating "a":4,"a":5 which is not valid JS and, in fact, returns the same SyntaxError Unexpected token :

Wrapping that code in parentheses (or, rather, a grouping operator) removes that ambiguity since an assignment expression cannot be followed by a block statement:

var test = {"a":"a","a":"b"}; //test.a === "b"

Furthermore this ambiguity can be removed by any operator or expression that cannot be used with a block statement. A practical scenario hardly comes to mind, maybe if you wanted to return an object literal as part of a conditional operator?

//this *could* come out of a JS minifier:
return x ? (foo(),{"a":"b"}) : (bar(), {"b":"a"});

Why should it not be accepted? You're simply overwriting the values. I think it's rather a feature, than an error. And it works fine for me on various browsers: http://jsbin.com/oculon/1/edit It's like writing

var a;

a = 4;
a = 5;

alert(a);

it's not Error you just overwrite value with another

I'm guessing (though not certain) that this evaluates as an error because of the difference between the way Firefox and Chrome's JS parsers treat statements and expressions. So because it's wrapped in parentheses the second time, it's considered an expression. Since it's looking for less information in an expression, it can ignore erroneous values. You'll see that if you do...

var a = {'a': 5, 'a': 4};
console.log(a);

It works fine! And also notice that here it's in the right hand side of the statement, giving a hint that it's an expression.

本文标签: Why is object with duplicated property accepted in JavaScriptStack Overflow