4

在 JS 控制台上玩时,我遇到了一个奇怪的语法。我想知道是否有人可以告诉我更多。

尝试这个:

>( function f(){console.log('i am f')} , (function x(){console.log('i am x')})() , y=2 , console.log('hello') )
i am x
hello
undefined
>f()
ReferenceError: f is not defined
>this.y
2

这将失败:

( var c=2 ) SyntaxError: Unexpected token var

所以括号内的逗号分隔表达式被评估,赋值恰好是针对全局范围的,但是命名函数声明引用就像闭包一样被困在里面...把那行放在一个用new调用的函数声明中:

function C(){
    ( function f(){console.log('i am f')} , (function x(){console.log('i am x')})() , y=2 , console.log('hello') )
}

然后实例化:

>var c=new C()
i am x
hello
undefined
>c.y
undefined
>this.y
2

完全一样,就像在全局范围内执行一样!

这个构造的用途/目的是什么?

多一个:

>( function f(){console.log('i am f')} , f() )
ReferenceError: f is not defined

所以命名函数不能在括号内引用。

4

2 回答 2

6

命名函数不会“被困在里面”,因为它们不是函数声明function用作语句),它们实际上是函数表达式function用作运算符)。这意味着它们的名称不会成为当前命名空间中对它们自己的引用。


某些关键字/标记只能用作语句,例如var,因此如果您尝试在解释器期望为表达式的条件下使用它们,则会引发错误。


至于y === 2,这是因为你没有var y;在里面C,所以y = 2设置window.y了,并且在全局范围内this === window


这个构造的用途/目的是什么?

  • 逗号运算符,允许您在一行上执行多个表达式。
  • 函数表达式对很多事情都很有用,无论是立即调用它们以便你有一个闭包,还是将它们存储在变量中等等。
于 2013-08-18T21:54:57.543 回答
4

将代码包装在括号中会强制将其解析为表达式。

var关键字仅作为语句有效,因此会产生语法错误。

函数声明可以是语句(创建提升变量)或表达式(不创建任何变量)。

因此,将函数包装在括号中会将其转换为函数表达式,它不会创建外部可见的名称。

有关详细信息,请参阅此处

于 2013-08-18T21:49:17.237 回答