为什么这里需要一个函数名?

3

我一直在FireFox浏览器控制台中测试这个,不确定其他JavaScript环境是否也有此功能:

◄ {x:function(){console.log("test");}}["x"]();
► SyntaxError: function statement requires a name

为什么?这个虽然能正常工作,但为什么呢:

◄ ({x:function(){console.log("test");}})["x"]();
► undefined
► "test"

(如果有人在想:我真的很讨厌 switch、case、break 语法。我宁愿使用这种结构。)

FYI:Chrome 给出“意外的标记(”错误。 - HaukurHaf
Chrome 在这里表现得很奇怪: {x:1} 1(一个?!) {x:1,y:2} 语法错误:意外的标记:“:”(啥?) - Stijn Sanders
啊,但 ({x:1,y:2}) 对象 {x: 1, y: 2}。 我猜这是一个语句<>表达式的问题。 - Stijn Sanders
4个回答

5
第一个中括号会导致块语句。注入分号后,第一个看起来像这样。
{
    x : function() { 
        console.log("test");
    }
};
["x"]();

3
JavaScript语法可以存在歧义。第一个例子被解析为开启块({)并跟随标签(x:, 你可以通过breakcontinue跳转到该标签),然后是函数声明。在声明函数时,您必须提供名称。
第二个示例被解析为表达式,因为它被圆括号(()括起来,所以{被解释为带有x属性的匿名对象,其值是函数表达式。函数语句可以是匿名的。

JavaScript 中没有 goto。标签与 breakcontinue 一起使用。 - James Montagne
JavaScript 怎么可能没有 goto?现在我知道为什么一些真正的程序员认为 JavaScript 是玩具编程语言了... - el.pescado - нет войне

2
这是因为你正在创建一个块。正如MDN所述

块语句用于将零个或多个语句分组。该块由一对花括号分隔。

这是一个块:
{}

这是一个语句,它不返回任何内容。它只是将零个或多个其他语句组合在一起。当Javascript在一行开头看到{时,它会认为“啊哈,我们有一个块在这里”。

然而,这并不是一个块:

({})

这是一个表达式。它有一个返回值。在这里,{} 在表达式上下文中表示对象字面量,而不是块。

因此,针对你的代码,我们来分解一下:

{ // start a block
    x: // create a label called x
    function(){console.log("test");} // create a function expression
} // end the block
["x"](); // create an array with one element and attempt to execute it as a function

现在,最后一行显然会失败,但我们永远不会到达那里。当Javascript在一行开头看到function时,它期望的是一个函数声明。你提供了一个匿名函数表达式,这在这个上下文中是无效的,会导致错误。
相比之下,你的另一个语句:
( // start an expression
    { // create an object
        x: function(){console.log("test");} // create a property called x with an anonymous function as its value
    } // end the object
) // end the expression and return the object
["x"] // get the `x` property from the returned object
(); // execute it

0
在Opera 12.16中,它基本上做了相同的事情,只是没有告诉你。
["x"] is not a function

这实际上并不是问题: 在你的第一个语句中,你定义了


{x:function(){console.log("test");}}

如果您自己输入此内容,它将被评估为:
function(){console.log("test");}

但是如果你不在它周围加上括号,它将只是评估为一个匿名对象,并在语句的其余部分消失。 如果你像这样加上一个点:

{x:function(){console.log("test");}}.x

如果你这样做,会出现语法错误。

({x:function(){console.log("test");}}).x

它会工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接