在几个 JavaScript 库中,我一开始就看到了这个符号:
/**
* Library XYZ
*/
;(function () {
// ... and so on
虽然我对“立即执行的函数”语法非常满意
(function(){...})()
我想知道前导分号是做什么用的。我能想到的就是它是一种保险。也就是说,如果该库嵌入到其他有缺陷的代码中,则它充当“最后一条语句最迟在此处结束”的一种减速带。
它还有其他功能吗?
在几个 JavaScript 库中,我一开始就看到了这个符号:
/**
* Library XYZ
*/
;(function () {
// ... and so on
虽然我对“立即执行的函数”语法非常满意
(function(){...})()
我想知道前导分号是做什么用的。我能想到的就是它是一种保险。也就是说,如果该库嵌入到其他有缺陷的代码中,则它充当“最后一条语句最迟在此处结束”的一种减速带。
它还有其他功能吗?
它允许您将多个 JavaScript 文件安全地连接为一个,以作为一个 HTTP 请求更快地提供服务。
最佳答案实际上是在问题中给出的,所以为了清楚起见,我将在这里写下来:
;
立即调用的函数表达式前面的前导是为了防止在连接期间将文件附加到包含未正确终止的表达式的文件时出错;
。
最佳做法是用分号终止表达式,但也使用前导分号作为保护措施。
一般来说,如果一个语句以 (, [, /, +, or - 开头,那么它就有可能被解释为之前语句的延续。以 /, +, 和 - 开头的语句在实践中是很少见的, 但是以 ( 和 [ 开头的语句并不少见, 至少在某些 JavaScript 编程风格中是这样。一些程序员喜欢在任何此类语句的开头放置一个防御分号, 以便即使语句在它被修改并删除之前终止的分号之前:
var x = 0 // Semicolon omitted here
;[x,x+1,x+2].forEach(console.log) // Defensive ; keeps this statement separate
来源:
这称为前导分号。
它的主要目的是保护自己免受先前未正确关闭的代码的影响,这可能会导致问题。分号可以防止这种情况发生。如果前面的代码没有正确关闭,那么我们的分号会纠正这个问题。如果它被正确关闭,那么我们的分号将是无害的,也不会产生副作用。
一个单行的答案是安全地连接多个 JavaScript 文件。使用分号不会引起问题。
假设你有多个函数:
IFE 1
(function(){
// The rest of the code
})(); // Note it is an IIFE
IIFE 2
(function(){
// The rest of the code
})(); // Note it is also an IIFE
在串联时,它可能看起来像:
(function(){})()(function(){})()
但是如果在函数前添加分号,它将如下所示:
;(function(){})();(function(){})()
因此,通过添加 a ;
,它会注意是否有任何表达式未正确终止。
示例 2
假设您有一个带有变量的 JavaScript 文件:
var someVar = "myVar"
另一个具有某些功能的 JavaScript 文件:
(function(){})()
现在在串联它看起来像
var someVar = "myVar"(function(){})() // It may give rise to an error
使用分号,它看起来像:
var someVar = "myVar";(function(){})()