为什么结果根据花括号的位置而有所不同?


118

为什么代码片段如下,取自这篇文章,产生不同的结果,由于只在大括号的放置一个变化?

当左花括号{在新行上时,test()返回undefined,并且警报中显示“ no-it break:undefined”。

function test()
{
  return
  { /* <--- curly brace on new line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}

当花括号与处于同一行时returntest()将返回一个对象,并警告“奇妙”。

function test()
{
  return { /* <---- curly brace on same line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}


之后的半插入语义return与其他地方略有不同,换行符在该位置“比在中间位置”的含义更多。
dandavis,2015年

Answers:


165

这是JavaScript的陷阱之一:自动分号插入。不以分号结尾但可能是语句结尾的行会自动终止,因此您的第一个示例实际上是这样的:

function test()
{
  return; // <- notice the inserted semicolon
  { 
    javascript: "fantastic"
  };
}

另请参见Douglas Crockford的JS样式指南,其中提到了分号插入。

在第二个示例中,您返回一个对象(由花括号构建),该对象的属性javascript及其值为"fantastic",实际上与此相同:

function test() {
    var myObject = new Object();
    myObject.javascript = "fantastic";
    return myObject;
}

5
趣闻:在某些引擎上,您可以注释掉自动插入的分号
Christopher Tarquini 2010年

1
@ChrisT:什么?哪个?在任何地方都可以探索吗?
肖恩·麦克米伦

1
@SeanMcMillan我已经明确阅读了有关它的文章,但是我似乎无法通过快速搜索找到它们。我记得在老版本的chrome中,放置return /*然后*/{ 可以有效地注释掉隐藏的分号。不确定是否仍然适用
Christopher Tarquini 2013年

2
由于这些怪癖,我10年前对自己许下了诺言:远离网络!我为Interwebs消失而祈祷...不幸的是,它并没有按计划进行,现在我也不得不为这些问题而苦苦挣扎。因果关系
abarma)

1
我见过一些人虔诚地反对JavaScript中的分号,我一直想知道他们如何利用不使用分号节省的额外时间来做什么。
伊曼·穆罕默迪

9

Javascript在语句末尾不需要分号,但是缺点是必须猜测分号在哪里。在大多数情况下,这不是问题,但有时它会发明一个您不想使用的分号。

我的博客文章中的一个示例(Javascript –几乎不是基于行的):

如果按以下格式设置代码:

function getAnswer() {
   var answer = 42;
   return
      answer;
}

然后将其解释为:

function getAnswer() {
  var answer = 42;
  return;
  answer;
}

return语句采用无参数形式,并且参数成为其自身的语句。

您的代码也是如此。该函数解释为:

function test()
{
  return;
  {
    javascript : "fantastic"
  };
}

3

我个人更喜欢Allman风格的可读性(对比K&R风格)。

代替…

function test() {
  return {
    javascript : "fantastic"
  };
}

我喜欢…

function test() 
{
  var obj =
  {
    javascript : "fantastic"
  };

  return obj;
}

但这是一种解决方法。我可以忍受。


3
我认为我们应该避免个人偏好偏离主流。我们应该遵循多数人的选择,这将促进一致性,从而提高可读性
Jowen

1
我发现他的代码比K&R更易读。当您说“可读”时,非常主观
布兰

我也更喜欢Allman ...但是由于ASI,当我需要返回对象时,我将半值与返回值放在同一行。我宁愿这样,也不愿添加一条“ var x =”行...
Mik

1

这是因为javascript最常将“;”放到 在每行的末尾,因此基本上,当您在同一行中返回{时,javascript引擎会看到还有更多内容,而当它在新行中时,它会认为您忘记了加“;”,并为您放了它。


1
我不明白为什么cichy,Darin和Ivo的答案被否决了?
BoltClock

1

此处的花括号指示新对象的构造。因此,您的代码等效于:

function test() {
  var a = { javascript : "fantastic" };
  return a;
}

这有效,而如果您写:

function test() {
  var a = { javascript : "fantastic" };
  return; // ; is automatically inserted 
      a;
}

它不再起作用。


0

问题确实是如上所述的分号注入。我刚刚读了一篇有关此主题的不错的博客文章。它解释了此问题以及有关javascript的更多信息。它还包含一些很好的参考。你可以在这里阅读


是的,我也读过,在此阅读,请JS的策划者更好地解释。
JustLearn'9
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.