34

下面的代码说明了一个被赋值的对象字面量,但后面没有分号:

var literal = {
    say: function(msg) { alert(msg); }
}
literal.say("hello world!");

这似乎是合法的,并且不会发出警告(至少在 Firefox 3 中)。这是完全合法的,还是有一个严格的 JavaScript 版本不允许这样做?

我特别想知道未来的兼容性问题......我想编写“正确的”JavaScript,所以如果从技术上讲我需要使用分号,我想使用它。

4

7 回答 7

39

从技术上讲,JavaScript 在许多情况下都可以选择分号。

但是,作为一般规则,在任何语句的末尾使用它们。为什么?因为如果您想压缩脚本,它将使您免于无数小时的挫败感。

自动分号插入由解释器执行,因此如果您愿意,可以将它们排除在外。在评论中,有人声称

对于 break/continue/throw 等语句,分号不是可选的

但这是不正确的。它们是可选的;真正发生的是行终止符会影响自动分号插入;这是一个微妙的区别。

以下是分号插入标准的其余部分:

然而,为方便起见,在某些情况下,这些分号可能会从源文本中省略。这些情况是这样描述的,在这些情况下分号会自动插入到源代码令牌流中。

于 2008-09-03T18:19:29.350 回答
16

YUI Compressor 和 dojo shrinksafe 在没有分号的情况下应该可以正常工作,因为它们基于完整的 JavaScript 解析器。但是 Packer 和 JSMin 不会。

在语句末尾始终使用分号的另一个原因是,有时您可能会不小心将两个语句组合在一起以创建非常不同的内容。例如,如果您遵循使用通用技术的语句来使用闭包创建范围:

var literal = {
    say: function(msg) { alert(msg); }
}
(function() {
    // ....
})();

解析器可能会将括号解释为函数调用,这会导致类型错误,但在其他情况下,它可能会导致难以跟踪的细微错误。另一个有趣的问题是,如果下一条语句以正则表达式开头,解析器可能会认为第一个正斜杠是除法符号。

于 2008-09-03T18:59:46.820 回答
8

JavaScript 解释器做了一种叫做“分号插入”的事情,所以如果没有分号的行是有效的,分号会悄悄地添加到语句的末尾,不会发生错误。

var foo = 'bar'
// Valid, foo now contains 'bar'
var bas =
    { prop: 'yay!' }
// Valid, bas now contains object with property 'prop' containing 'yay!'
var zeb =
switch (zeb) {
  ...
// Invalid, because the lines following 'var zeb =' aren't an assignable value

不太复杂,至少当某些事情明显不正确时会引发错误。但是有些情况下没有抛出错误,但是由于分号插入,语句没有按预期执行。考虑一个应该返回对象的函数:

return {
    prop: 'yay!'
}
// The object literal gets returned as expected and all is well
return
{
    prop: 'nay!'
}
// Oops! return by itself is a perfectly valid statement, so a semicolon
// is inserted and undefined is unexpectedly returned, rather than the object
// literal. Note that no error occurred.

像这样的错误很难找到,虽然你不能确保这种情况永远不会发生(因为我不知道关闭分号插入),但当你通过以下方式明确意图时,这些错误更容易识别始终使用分号。这和明确添加分号通常被认为是好的风格。

在阅读Douglas Crockford 的精妙而简洁的著作《JavaScript: The Good Parts 》时,我第一次意识到了这种隐蔽的小可能性。我强烈推荐它。

于 2008-09-03T20:32:06.863 回答
3

在这种情况下,语句末尾不需要分号。结论是一样的,但推理却很遥远。

JavaScript 没有分号作为“可选”。相反,它对自动分号插入有严格的规定。对于, 或等语句break,分号不是可选的。有关详细信息,请参阅ECMA 语言规范;特别是11.9.1,自动分号插入规则continuethrow

于 2008-09-03T19:04:08.790 回答
0

使用JSLint保持你的 JavaScript 干净整洁

JSLint 说:

错误:

隐含全局:警报 2

第 3 行字符 2 的问题:缺少分号。

}

于 2008-09-03T18:20:21.610 回答
0

分号不是必需的。有些人选择遵循总是以分号结尾的惯例,而不是让 JavaScript 在换行时自动这样做,但我相信你会发现一些团体提倡任一方向。

如果您正在考虑编写“正确”的 JavaScript,我建议您在 Firefox 中将javascript.options.strict(accessed via about:config) 设置为 true 进行测试。它可能无法捕获所有内容,但它应该可以帮助您确保您的 JavaScript 代码更加兼容。

于 2008-09-03T18:29:03.320 回答
-1

这是无效的(请参阅下面的说明)JavaScript 代码,因为赋值只是一个常规语句,与

var foo = "bar";

由于 JavaScript 解释器尝试添加分号来修复语法错误,因此可以省略分号,但这是一个额外且不必要的步骤。我不知道任何严格模式,但我知道自动解析器或压缩器/混淆器需要那个分号。

如果您想编写正确的 JavaScript 代码,请编写分号 :-)

根据 ECMAscript 规范http://www.ecma-international.org/publications/standards/Ecma-262.htm,如果缺少分号,则会自动插入分号。这使得脚本作者不需要它们,但这意味着解释器需要它们。这意味着原始问题的答案是“否”,编写脚本时不需要它们,但是正如其他人指出的那样,出于各种原因建议使用它们。

于 2008-09-03T18:21:53.680 回答