何时应在花括号后使用分号?

67
在函数声明后面或模块模式脚本的匿名“return”函数后面,我经常看到分号的使用。何时在花括号后面使用分号是合适的呢?
8个回答

109

在语句后使用分号。这是一个语句:

var foo = function() {
  alert("bar");
};

因为这是一个变量赋值(即创建并将匿名函数分配给变量)。

让我想到的两件不是语句的事情是函数声明:

function foo() {
  alert("bar");
}

以及区块:

{
  alert("foo");
}

注意:同样不带分号的代码块结构也适用于fordowhile循环。


还有在 var foo = {"prop1":1,"prop2":2}; 等之后。 - Robusto
4
@Robusto 这是一个变量赋值操作。 - cletus
2
@SLaks 我知道,它需要一个分号,因为它是一个变量赋值(这就是我的观点)。 - cletus
@Cletus:只是想扩展一下你的话,这样 OP 就不会认为你只是指函数字面量。 - Robusto
2
这同样适用于 if 语句。 - mbomb007
显示剩余2条评论

25

@alegz 对我来说可行。 - alex

20

不要使用分号:

……如果这只是你每天的函数声明:

function foo() {

} // No semicolon

使用分号:

......如果这是一个赋值语句:

var foo = function() {

}; // Semicolon


...或者是自执行函数:

(function () {

})(); // Semicolon

10

你不需要添加分号,但你总是可以这样做(除了在elsewhile之前)。

解释:

遗憾的是,JavaScript中的分号是可选的。
因此,你不必添加分号。

在每个语句结尾添加分号是一个(非常)好的习惯。
唯一以}结尾的语句是那些以对象字面量(例如JSON)或函数表达式结尾的语句。

因此,最佳实践是仅在以下两个括号后面加上分号:

var myFunc = function() { };
var myobject = { };

使用 function someFunc(){ }; 仍然需要分号作为语句吗? - ilyo
1
如果你想让压缩后的Javascript在IE中正常工作,那么你必须加上分号。我发现只有IE会因为没有分号而出现问题,而Firefox/Chrome/Safari则无所谓语句后面是否有分号。 - Cerin
@Cerin:我不认为那是真的。 - SLaks
@SLaks,你自己试试看。不加分号压缩JS代码,然后在IE9上运行它。我刚刚浪费了几个小时的时间来解决这个问题。想和其他人分享这个麻烦。 - Cerin
@ Cerin:我尝试过在IE9中运行它。你能分享一下你用来测试的压缩示例吗? - monish001

5
如果我们有一个自调用函数,我们需要在它之前放置一个分号,否则它就成为了上一个赋值语句的一部分。考虑以下代码:
testClass = function(name) {
  document.write ("Instantiating testClass<br />");
  this.name = name;
}

testClass.prototype.report = function() {
  document.write ("I'm " + this.name + "<br />");
  return 1;
}

testClass.prototype.testMethod = function(param) {
  document.write ("Running testMethod with parameter value " + param + "<br />");
  return 2;
} // notice that there is no semicolon here

(function() {
  document.write ("Running self-invoking function<br />");
  return 3;
}());

if (typeof(testClass.prototype.testMethod) !== "function") {
  document.write ("testMethod type: " + typeof(testClass.prototype.testMethod));
  document.write (", value: " + testClass.prototype.testMethod + "<br />");
}
var testOb = new testClass("Bill");
testOb.report();
testOb.testMethod(4);

这将产生以下输出:

“运行自执行函数
使用参数值3运行testMethod
testMethod类型:数字,值为2
实例化testClass
我是Bill”

…加上浏览器报告的一个JavaScript错误:testOb.testMethod不是函数

这显然不是我们想要的。为什么在我们实例化类之前就立即运行了testMethod?为什么当我们作为成员方法调用它时,它不再存在?

发生的情况是,testMethod被分配的不是我们的函数定义,而是函数定义的返回值。函数定义本身是匿名运行的。原因如下:

  1. testClass的构造函数和成员方法report已成功定义/分配。
  2. 由于在testMethod的定义后缺少分号,因此紧随其后的自执行函数周围的()变成了调用运算符,导致我们认为的testMethod的定义变成了一个匿名函数,该匿名函数立即被调用,并且以下匿名函数的返回值成为其参数列表。这解释了打印输出的顺序 - 我们的自执行函数首先运行,因为它被评估为参数。
  3. 由于我们预期的函数定义返回2,因此将此2分配给testMethod,而不是将其赋值为函数定义。我们打印testMethod的类型和值证实了这一点。
  4. 现在testClass已成功实例化为testOb,并且其report方法按预期工作,证明类定义是完好无损的。
  5. 当我们试图调用testMethod时,解释器告诉我们它不是一个函数 - 这是正确的,因为它是一个值为2的数字。

如果我们在testMethod的定义后放置分号,则会将其分配从自执行函数的调用中分离出来,我们就会得到预期的结果:

“运行自执行函数
实例化testClass
我是Bill
使用参数值4运行testMethod”



或者我们甚至可以将其直接放在匿名函数之前:

;(function() {...

但是我建议,由于问题是由于在赋值语句末尾缺少分号导致的,因此我们应该养成在这种方式定义函数后始终加上分号的习惯。也就是说,在闭合大括号之后,所有的函数都应该有一个分号,因为它们都是匿名函数的赋值。


3
在JavaScript中,如果在函数内部返回另一个函数时,在花括号后面应使用分号。
function watchOut(problem) {
  return function(number, location) {
    alert("Be careful! There are " + problem +
          " today!\n" +

          number + " have been spotted at the " + location + "!"
    );
  };
}

0

考虑以下代码:

// This will break code

a=b=c=d=e=1
a = b + c     // Semicolon required here
(d + e).toString()

它将返回“对象[object Object]的属性不是函数”。因为它实际上将被执行为:
a = b + c(d + e).toString()

-1
分号放在不以花括号结尾的行末或用于分隔同一行上的语句。在闭合花括号后使用它们或同时使用吊带和腰带并不会造成任何伤害,但看起来有点书呆子。

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