2012-11-08 38 views
9

我期待JavaScript拒绝具有重复属性的对象作为无效,但在某些情况下它会接受它们。为什么在JavaScript中接受具有重复属性的对象?

{"a":4,"a":5}至少在Firefox和Chrome中导致一个SyntaxError,由于属性a被定义了两次,这似乎是显而易见的。

({"a":4,"a":5})的评估结果很好,并在Firefox和Chrome中导致对象{"a":5}

为什么用括号表达接受?

总结回复:第一个例子根本不是一个对象的构造,而是一组标记语句。在最后一个定义获胜的情况下,对象中的重复属性完全有效。

非常感谢您的回答!

+1

似乎在FF和Chrome http://jsbin.com/iponud/1/edit上有和没有括号一起正常工作。我的意思是它返回最后一个'a' – elclanrs

+0

@elclanrs:这个结果是有误导性的(我在jsfiddle早些时候自己就这么做了:) - 将代码放在'console.log'参数列表中去掉[句法含糊不清,导致在第一个地方的错误](http://stackoverflow.com/a/13287483/1081234) –

回答

3

你的国家,什么东西有没有问题,如果你把它分配给一个变量,如果你不这样做但是,你得到你提到的错误。从语法的角度来看,这一切都有所不同。

当您缠绕在括号的任何结构你正在导致该语法被作为表达,其结果被存储为临时变量进行评价。在Firefox不这样做的时候,所以我得到的错误是意想不到的标签无效标签,因此它似乎没有分配,或括号,此对象的构造不被视为一个对象的构造 - 相反,它被视为具有多块被非法定义标签声明:

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

以上应该是作为一个对象完全可以接受的,但是如果你评估它,你得到一个类似的错误,没有它assinging某种形式的变量,或用括号评测吧。简而言之属性名称的重复不会导致错误:)

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

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

这大致如何将这些浏览器处理它,这是现在很明显非法的JavaScript语法...而之前并不那么明显。

0

为什么它不被接受?你只是简单地重写值。我认为这是一个功能,而不是一个错误。它工作正常,我在各种浏览器:http://jsbin.com/oculon/1/edit 这就像写

var a; 

a = 4; 
a = 5; 

alert(a); 
4

它是ECMAScript中3完全合法的对象文本申报重复属性;你可能是SyntaxError来自于你所使用的对象字面的说法,这是不可能的,因为与语句块中的困惑({ doSomething(); })的事实。

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

+0

+1关于严格模式的好处。 – Pebbl

+1

有趣的是,在ECMAScript 6的严格模式下,重复的属性名称完全可以。人们注意到,当您事先不知道属性名称时,编写没有语法错误的对象文字会有点棘手。 – Robert

0

这不是错误,你只是简单地覆盖价值与另一

0

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

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

它工作正常!另外请注意,这里是在声明的右边,暗示它是一个表达式。

2

在第一个符号(无括号)中,javascript语法不明确。从ecmascript specification

ExpressionStatement不能以大括号 开始,因为这可能使含糊带

一个block基本评估中的所有语句,相当于评估"a":4,"a":5这是无效的JS,事实上,返回相同的SyntaxError 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"}); 
相关问题