为什么在JS上进行这种不良设计?有什么特殊的理由来设计这样的自动分号?
这是我的代码,在chrome的js中不起作用:
(function(){console.log("abc");})()
(function(){console.log("123");})();
这是错误:
Uncaught TypeError: (intermediate value)(...) is not a function
我知道这段代码的正确版本是:
(function(){console.log("abc");})();
(function(){console.log("123");})();
我只想知道为什么js语法设计得如此愚蠢。历史原因?
我还将这个问题作为警告,警告大家尝试使用javascript自动分号插入,只要在需要的地方添加;
,javascript的自动分号就是垃圾。它不符合您的期望。
存在的答案对我来说太复杂了,所以我问一个新的答案:
https://stackoverflow.com/a/2846298/1586797
另一个看起来不错,但无法解决问题2:
x=1
(function(){console.log("123");})()
答案 0 :(得分:3)
链接的问题的答案解释了规范针对ASI的三个规则,例如this one。 tl; dr:
如果它不起作用,请尝试使用分号。
程序应以分号结尾。
如果一条语句说“不能在此处放置换行符”,请用分号对其进行惩罚。
您的代码不满足任何条件。
第一行可以返回一个函数,如果可以,则应允许该函数被调用;因此第二行开头的(
不合法
第一行不是程序的最后一行
此处没有语法限制。
因此,没有适合您的自动分号。
因此,有人声称(f(){})()
语法是很好的IIFE语法,但最好改用!f(){}()
:
!function(){console.log("abc");}()
!function(){console.log("123");}();
这是按预期的方式工作的,因为!
仅仅抵消了函数应用程序的(丢弃)结果,并且因为!
作为纯一元运算符是继续第一行的非法字符(即{ 1}}不是问题。这会触发规则1,ASI就会发生。
反对意见是,这种说法很丑陋(即,对于尚不熟悉该做法的任何人,他们花一些时间才能理解此成语中f(){}()!
的目的)。
您的第二个示例在本质上是相似的:就JS解析器而言,!
是一个值(它是一个整数并且不可能是一个函数的事实让它有些失落) 。看这个示例,它在语法上完全等同于您的示例:
1
这里a=function(f) { console.log("A CALLED!"); return f; }
x=a
(function(){console.log("123");})()
# => A CALLED!
123
是一个函数,因此可以使用a
作为参数来调用它;打印到控制台后,它返回function(){console.log("123");}
不变;然后function(){console.log("123");}
调用该返回值,同时也显示()
。一切正常。因此,规则#1不会被触发,您也不需要分号。
答案 1 :(得分:2)
如果没有分号,则这些语句将被链接。您调用第一个函数,并将第二个func作为第一个函数的返回值的参数。如果第一个函数有一个函数作为返回值,那么这实际上可以工作。
扩展代码时,它变得更加明显:
repositories {
maven()
//other repositories...
google()
}
最后两行变为:
var a = function(){console.log("abc");};
var b = function(){console.log("123");}
(a)()
(b)();
这等同于
(a)()(b)();
由于var x = a();
x(b);
不返回任何内容,因此无法使用a
作为参数将其作为函数调用。
答案 2 :(得分:2)
b
等效于:
(function(){console.log("abc");})()
(function(){console.log("123");})();
通常称为函数curring。
对于IIFE(立即调用的函数表达式),您需要以(function(){console.log("abc");})()(function(){console.log("123");})();
有关函数循环的更多信息,请参见this post。显然,您的控制台日志功能不能用作currying函数,但是语法;
是用于currying的语言的一个很酷的功能。
答案 3 :(得分:2)
您的代码可以简化为:
(function(){})()()();
此代码将得到相同的错误。
()
需要一个表达式来调用。
第一个()
调用(function(){})
,第二个()
调用(function(){})()
的结果,但该结果不是函数,因此是错误的。
答案 4 :(得分:1)
如果您使用此方法,我认为这会更清楚:
x=1
(function(){console.log("123");})()
错误状态1
不是函数。明确说明(function...)
被视为对1
的函数调用的参数:
x=1(function(){console.log("123");})()
答案 5 :(得分:1)
因为()()是self-invoking函数,而();()是两个不同的函数,所以解释器会相应地对其进行解释。
这两个代码对于解释器是完全不同的。
(function(){console.log("abc");})()(function(){console.log("123");})();
和
(function(){console.log("abc");})();(function(){console.log("123");})();
但是,此代码可以正常工作
var a=12
var b=10
console.log(a+b)
答案 6 :(得分:1)
长答案排序:
(function(){console.log("abc");})()
试图立即调用前面的表达式
(function(){console.log("123");})();
这将是前面的IIFE的返回值。
IIFE在缺少分号的情况下可以采取不同的行动。这就是为什么我们看到如下代码的原因:
;(function() {
console.log('abc');
})()
请在此处查看详细说明:https://gist.github.com/khellang/8518964