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

Raj*_*hal 91 javascript language-agnostic programming-languages language-design

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

在Javascript中,在某些情况下,如果大括号的起始位置不同,则会有所不同.

function test_function1() {
    return
    {
        name: 'rajat'
    };
}

var obj = test_function1();
alert(obj);  //Shows "undefined"
Run Code Online (Sandbox Code Playgroud)

function test_function2() {
    return {
        name: 'rajat'
    };
}

var obj = test_function2();
alert(obj); //Shows object
Run Code Online (Sandbox Code Playgroud)

JSfiddle演示

有没有其他语言有这种行为?如果是这样,那么我肯定要改变我的习惯.. :)

我主要关注PHP,C,C++,Java和ruby.

Kon*_*lph 53

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

>>> def foo():
...   return
...   { 1: 2 }
... 
>>> def bar():
...   return { 1: 2 }
... 
>>> foo()
>>> bar()
{1: 2}
Run Code Online (Sandbox Code Playgroud)

你可能能够在Visual Basic中构建一个类似的案例,但是我无法弄清楚是怎么回事,因为VB在可能放置值的地方非常严格.但是除非静态分析器抱怨无法访问的代码,否则以下情况应该有效:

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
Run Code Online (Sandbox Code Playgroud)

从您提到的语言中,Ruby具有相同的属性.PHP,C,C++和Java不仅仅是因为它们将换行符丢弃为空格,并且需要使用分号来分隔语句.

这是Ruby中Python示例的等效代码:

>> def foo
>>   return { 1 => 2 }
>> end
=> nil
>> def bar
>>   return
>>   { 1 => 2 }
>> end
=> nil
>> foo
=> {1=>2}
>> bar
=> nil
Run Code Online (Sandbox Code Playgroud)

  • 您的VB示例并不能说明问题,因为VB*never*允许语句跨越多行,除非您使用行继续序列"_". (2认同)
  • 好吧我收回了之前的评论,因为我只是看了一下规范,其中有一些VB.NET支持隐式行延续的上下文.我怀疑任何有经验的VB程序员都会认为这个例子是"陷阱",但是,因为很明显`Throw`和`ex.GetBaseException()`是不同的逻辑行.更具体地说,由于Basic历史上使用行来分隔其语句,因此"getcha"更可能是程序员认为他在新逻辑行上创建了新语句但却没有. (2认同)

Ale*_*ian 40

;如果找不到,那么JavaScript解释器会在每行的末尾自动添加一个(除了一些例外,这里没有进入它们:).

所以基本上问题不在于大括号的位置(这里代表一个对象文字,而不是大多数语言中的代码块),但是这个小"特征"强迫你的第一个例子return ;=> undefined.您可以查看return ES5规范中的行为.

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

  • 高度赞成的答案,但它实际上是错误的,抱歉.解释很好,但请纠正错误. (5认同)
  • 但是JS在"每行末尾"插入分号并不是真的,"但有一些例外"; 相反,它通常*不会*插入分号,并且只有少数情况**会*.这就是为什么它会导致如此多的陷阱. (5认同)

Dav*_*ave 26

当然可以.谷歌的编程语言呈现出非常相似的行为(尽管有不同的效果).如上所述:

事实上,正式语言使用分号,就像在C或Java中一样,但它们会自动插入到每个看起来像语句结尾的行的末尾.您不需要自己键入它们.

..snip ...

这种方法可以实现外观整洁,无分号的代码.令人惊讶的是,将if语句等构造的左大括号放在与if相同的行上是很重要的.如果不这样做,有些情况可能无法编译或可能给出错误的结果.语言在某种程度上强制支撑风格.

偷偷地说,我认为Rob Pike只是想借口要求One True Brace Style.

  • 很酷,不知道这个:).就个人而言,我认为自动分号插入不是一个好主意.它可以引入人们对语言缺乏经验的微妙错误将很难搞清楚.如果你想写分号免费代码,我更喜欢python方式. (10认同)

jAn*_*ndy 14

这个问题的答案相当容易.任何具有"自动分号插入"的语言都可能在该行上出现问题.这个问题

return
{
     name: 'rajat'
};
Run Code Online (Sandbox Code Playgroud)

..是js引擎将在return;语句后插入一个分号(因此返回undefined).这个例子是一个很好的理由,总是在右侧打开花括号,也从不在左侧.由于您已经正确注意到,如果同一行中有一个大括号,解释器会注意到并且不能插入分号.


Bra*_*dan 6

FWIW,JSLint使用该语法报告了几个警告:

$ 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)
Run Code Online (Sandbox Code Playgroud)