JavaScript之外的任何其他语言在大括号开始位置(同一行和下一行)之间是否有区别?

Does any other language other than JavaScript have a difference between brace start locations (same line and next line)?

今天,当我随机阅读Javascript模式O'Reilly的书时,我发现了一件有趣的事情(参考第27页)。

在JavaScript中,在某些情况下,如果大括号的起始位置不同,则会有差异。

1
2
3
4
5
6
7
8
9
function test_function1() {
    return
    {
        name: 'rajat'
    };
}

var obj = test_function1();
alert(obj);  //Shows"undefined"

同时

1
2
3
4
5
6
7
8
function test_function2() {
    return {
        name: 'rajat'
    };
}

var obj = test_function2();
alert(obj); //Shows object

JSfiddle演示

有没有其他语言有这样的行为?如果是这样的话,那么我肯定得改变我的习惯。

我主要关注PHP、C、C++、Java和Ruby。


任何不依赖分号(而是换行)来分隔语句的语言都可能允许这样做。考虑python:

1
2
3
4
5
6
7
8
9
10
>>> def foo():
...   return
...   { 1: 2 }
...
>>> def bar():
...   return { 1: 2 }
...
>>> foo()
>>> bar()
{1: 2}

您可能可以在VisualBasic中构造类似的案例,但在我的头脑中,我无法理解如何使用VB,因为它对值的放置位置有很大的限制。但是,除非静态分析器抱怨无法访问的代码,否则以下内容应该有效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Try
    Throw New Exception()
Catch ex As Exception
    Throw ex.GetBaseException()
End Try

' versus

Try
    Throw New Exception()
Catch ex As Exception
    Throw
    ex.GetBaseException()
End Try

从您提到的语言来看,Ruby具有相同的属性。PHP、C、C++和Java不仅仅是因为它们将新行丢弃为空白,而且需要分号来分隔语句。

下面是Ruby中的python示例中的等效代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
>> def foo
>>   return { 1 => 2 }
>> end
=> nil
>> def bar
>>   return
>>   { 1 => 2 }
>> end
=> nil
>> foo
=> {1=>2}
>> bar
=> nil


javascript解释器会在每行末尾自动添加一个;,如果找不到(除了一些例外,这里不涉及它们)。

因此,基本上问题不在于大括号的位置(这里表示的是一个对象文本,而不是大多数语言中的代码块),而在于这个小的"特性",它迫使您的第一个示例使用return ;=>undefined。您可以在ES5规范中查看return的行为。

对于其他具有类似行为的语言,请查看Konrad的答案。


当然。谷歌的Go编程语言表现出非常相似的行为(尽管效果不同)。如前所述:

In fact, what happens is that the formal language uses semicolons, much as in C or Java, but they are inserted automatically at the end of every line that looks like the end of a statement. You don't need to type them yourself.

..snip...

This approach makes for clean-looking, semicolon-free code. The one surprise is that it's important to put the opening brace of a construct such as an if statement on the same line as the if; if you don't, there are situations that may not compile or may give the wrong result. The language forces the brace style to some extent.

私下里,我认为罗伯·派克只是想找个借口来要求一个真正的支撑方式。


这个问题的答案相当简单。任何具有"自动分号插入"的语言都可能在该行中遇到问题。这个问题

1
2
3
4
return
{
     name: 'rajat'
};

..是JS引擎将在return;语句后插入分号(因此返回undefined)。这个例子是一个很好的理由打开花括号总是在右边,而不是在左边。由于您已经正确地注意到,如果同一行中有一个花括号,那么解释程序将注意到这一点,并且不能插入分号。


fwiw,jslint报告了几种使用该语法的警告:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ jslint -stdin
function foo(){
  return
  { x:"y" };
}
^D
(3): lint warning: unexpected end of line; it is ambiguous whether these lines are part of the same statement
  return
........^

(3): lint warning: missing semicolon
  { x:"y" };
..^

(3): lint warning: unreachable code
  { x:"y" };
..^

(3): lint warning: meaningless block; curly braces have no impact
  { x:"y" };
..^

(3): lint warning: use of label
  { x:"y" };
.....^

(3): lint warning: missing semicolon
  { x:"y" };
...........^

(3): lint warning: empty statement or extra semicolon
  { x:"y" };
............^


0 error(s), 7 warning(s)

我遇到的第一种语言是awk(它也有语法"oddities"的部分;可选的分号、仅使用空格的字符串连接等等…)我认为DTrace设计人员(松散地基于awk的D语法)有足够的判断力不去复制这些特性,但我记不清这些特性。一个简单的例子(从我的Mac计算DTD中实体标记的数量):

1
2
3
4
5
6
7
$ cat printEntities.awk
# This prints all lines where the string ENTITY occurs
/ENTITY/ {
  print $0
}
$ awk -f printEntities.awk < /usr/share/texinfo/texinfo.dtd | wc -l
     119

如果这个小脚本是用大括号自己一行写的,那么会发生以下情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ cat printAll.awk
# Because of the brace placement, the print statement will be executed
# for all lines in the input file
# Lines containing the string ENTITY will be printed twice,
# because print is the default action, if no other action is specified
/ENTITY/
{
   print $0
}
$ awk -f printAll.awk < /usr/share/texinfo/texinfo.dtd | wc -l
     603
$ /bin/cat < /usr/share/texinfo/texinfo.dtd | wc -l
     484
$