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

时间:2012-11-08 09:26:44

标签: javascript

我希望JavaScript能够将具有重复属性的对象拒绝为无效,但在某些情况下它会接受它们。

{"a":4,"a":5}至少在Firefox和Chrome中产生SyntaxError,由于属性a被定义了两次,这似乎很明显。

然而,({"a":4,"a":5})评估得很好,并且在Firefox和Chrome中都会产生对象{"a":5}

为什么接受括号的表达式?

总结回复:第一个例子不是构造一个对象而是一个带标签的语句块。对象中的重复特性完全有效,在这种情况下,最后一个定义获胜。

非常感谢您的回答!

6 个答案:

答案 0 :(得分:5)

在ECMAScript 3中声明对象文字中的重复属性是完全合法的;您获得的SyntaxError可能来自于您使用对象文字作为语句这一事实,由于与块语句的混淆({ doSomething(); }),这是不可能的。

如果您希望将此报告为错误,您可能需要切换到ECMAScript 5的严格模式:https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode

答案 1 :(得分:4)

如果您将其分配给变量,那么您声明的内容没有问题,但如果不这样做,则会出现您提及的错误。从语法的角度来看,这就完全不同了。

当您在parens中包装任何结构时,您将使该语法被计算为表达式,其结果存储为临时变量。我在Firefox中没有这样做的错误是意外标签无效标签,所以似乎没有赋值或者parens,这个对象构造不被视为对象构造 - 相反,它被视为具有多个非法定义的标签语句的块:

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

上述内容应该完全可以接受为一个对象,但是如果你在没有将其赋予某种形式的变量的情况下进行评估,或者用parens进行评估,则会出现类似的错误。简单地说,重复属性名称不会导致错误:)

基本上想象你的第一个例子,但是像这样:

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

这大致是这些浏览器如何对待它,现在显然是非法的javascript语法......但之前并不那么明显。

答案 2 :(得分:2)

在第一种表示法(无括号)中,javascript语法不明确。来自ecmascript specification

  

ExpressionStatement 无法以大括号开头   因为这可能会使 Block 模糊不清。

block 基本上评估内部的所有语句,相当于评估无效JS的"a":4,"a":5,实际上返回相同的语法错误Unexpected token :

将该代码包含在括号中(或者更确切地说, a grouping operator )可以消除这种歧义,因为赋值表达式后面的语句不能跟随它:

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

此外,任何不能与块语句一起使用的运算符或表达式都可以消除这种歧义。一个实际的场景很难想到,也许你想将一个对象文字作为条件运算符的一部分返回?

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

答案 3 :(得分:0)

为什么不接受?你只是覆盖了这些值。我认为这是一个功能,而不是错误。它适用于各种浏览器:http://jsbin.com/oculon/1/edit 这就像写作

var a;

a = 4;
a = 5;

alert(a);

答案 4 :(得分:0)

这不是错误,你只是用另一个

覆盖值

答案 5 :(得分:0)

我猜测(虽然不确定)由于Firefox和Chrome的JS解析器处理语句和表达式的方式不同,因此评估为错误。因为它第二次被括在括号中,所以它被认为是一个表达式。由于它在表达式中寻找较少的信息,因此可以忽略错误的值。你会看到,如果你这样做......

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

工作正常!并且还注意到它在声明的右侧,提示它是一个表达式。