提问者:小点点

函数前的感叹号是做什么的?


!function () {}();

共3个答案

匿名用户

JavaScript语法101。 下面是一个函数声明:

function foo() {}

注意没有分号:这只是一个函数声明。 您需要调用foo()来实际运行函数。

现在,当我们添加一个看似无伤大雅的感叹号:!function foo(){}时,它将它转换成一个表达式。 它现在是一个函数表达式。

当然,本身并不能调用该函数,但是我们现在可以将()放在末尾:!函数foo(){}(),它的优先级高于,并立即调用该函数。

所以作者所做的是为每个函数表达式保存一个字节; 一种更易读的写作方式是:

(function(){})();

最后,使表达式返回true。 这是因为默认情况下,所有生命都返回undefined,这就留下了!undefined,它是true。 不是特别有用。

匿名用户

功能:

function () {}

不返回任何内容(或未定义)。

有时我们想在创建函数时调用它。 您可能想尝试一下:

function () {}()

但会导致语法错误

在函数之前使用运算符会使它被视为表达式,因此我们可以调用它:

!function () {}()

这还将返回函数返回值的布尔相反值,在本例中为true,因为!undefinedtrue。 如果您希望实际返回值是调用的结果,那么可以尝试这样做:

(function () {})()

匿名用户

在《爱彼迎JavaScript指南》中,有一个很好的方法是使用进行函数调用

通常,在单独的文件(也就是模块)上使用这种技术的想法,这些文件后来会被连接起来。 这里需要注意的是,文件应该由将新文件放在新行的工具连接起来(这是大多数concat工具的常见行为)。 在这种情况下,使用将有助于避免在if先前连接的模块缺少尾随分号时出错,但这将提供灵活性,使它们可以毫无顾虑地按任何顺序排列。

!function abc(){}();
!function bca(){}();

工作原理与

!function abc(){}();
(function bca(){})();

但节省了一个字符和任意看起来更好。

顺便说一下,任何+-~void运算符在调用函数方面都具有相同的效果,当然,如果您必须使用某个函数返回,它们的操作会有所不同。

abcval = !function abc(){return true;}() // abcval equals false
bcaval = +function bca(){return true;}() // bcaval equals 1
zyxval = -function zyx(){return true;}() // zyxval equals -1
xyzval = ~function xyz(){return true;}() // your guess?

但是如果您使用iLife模式进行一个文件一个模块的代码分离,并使用concat工具进行优化(这使得一行一个文件的作业),那么构造

!function abc(/*no returns*/) {}()
+function bca() {/*no returns*/}()

将执行安全的代码,与第一个代码示例相同。

这将引发错误,因为JavaScript ASI将无法执行其工作。

!function abc(/*no returns*/) {}()
(function bca() {/*no returns*/})()

关于一元运算符的一个注意事项是,它们会做类似的工作,但只是在第一个模块中不使用它们的情况下。 因此,如果您不能完全控制连接顺序,它们就不那么安全。

这是可行的:

!function abc(/*no returns*/) {}()
^function bca() {/*no returns*/}()

这不是:

^function abc(/*no returns*/) {}()
!function bca() {/*no returns*/}()