简体   繁体   English

为什么在JavaScript中接受具有重复属性的对象?

[英]Why is object with duplicated property accepted in JavaScript?

I was expecting JavaScript to reject objects with duplicated properties as invalid but it accepts them in some cases. 我希望JavaScript能够将具有重复属性的对象拒绝为无效,但在某些情况下它会接受它们。

{"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. {"a":4,"a":5}导致一个SyntaxError至少在Firefox和铬这似乎是显而易见的,由于属性a被定义的两倍。

However ({"a":4,"a":5}) evaluates just fine and results in an object {"a":5} in both Firefox and Chrome. 但是({"a":4,"a":5})评估得很好,并在Firefox和Chrome中产生一个对象{"a":5}

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! 非常感谢你的回答!

It is perfectly legal in ECMAScript 3 to declare duplicate properties in an object literal; 在ECMAScript 3中声明对象文字中的重复属性是完全合法的; 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(); } ). 您获得的SyntaxError可能来自于您使用对象文字作为语句的事实,由于与块语句的混淆( { 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 . 如果您希望将此报告为错误,您可能需要切换到ECMAScript 5的严格模式: 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. 当您在parens中包装任何结构时,您将使该语法被计算为表达式,其结果将存储为临时变量。 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: 我在Firefox中没有这样做的错误是意外的标签无效的标签 ,所以看起来没有赋值或者parens,这个对象构造不被视为对象构造 - 而是被视为具有多个标签语句的块。非法定义:

{
  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. 作为一个对象,上面的内容应该是完全可以接受的,但是如果你在没有将它添加到某种形式的变量的情况下进行评估,或者用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. 这大致是这些浏览器如何对待它,现在显然是非法的javascript语法......而它之前并不那么明显。

In the first notation (parentheses-less) the javascript syntax is ambiguous. 在第一种表示法(无括号)中,javascript语法不明确。 From ecmascript specification : 来自ecmascript规范

An ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block . ExpressionStatement不能以开括花括号开头,因为这可能使其与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 : 一个基本上评估了里面的所有语句,相当于评估"a":4,"a":5这是无效的JS,实际上,返回相同的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 它适用于各种浏览器: http//jsbin.com/oculon/1/edit就像写作一样

var a;

a = 4;
a = 5;

alert(a);

你只是用另一个覆盖价值,这不是错误

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. 我猜测(虽然不确定)由于Firefox和Chrome的JS解析器处理语句和表达式的方式不同,因此评估为错误。 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. 并且还注意到它在声明的右侧,提示它是一个表达式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM