我希望JavaScript能够将具有重复属性的对象拒绝为无效,但在某些情况下它会接受它们。
{"a":4,"a":5}
至少在Firefox和Chrome中产生SyntaxError
,由于属性a
被定义了两次,这似乎很明显。
然而,({"a":4,"a":5})
评估得很好,并且在Firefox和Chrome中都会产生对象{"a":5}
。
为什么接受括号的表达式?
总结回复:第一个例子不是构造一个对象而是一个带标签的语句块。对象中的重复特性完全有效,在这种情况下,最后一个定义获胜。
非常感谢您的回答!
答案 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);
工作正常!并且还注意到它在声明的右侧,提示它是一个表达式。