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

发布于 2025-01-03 18:16:20 字数 590 浏览 5 评论 0原文

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

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

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

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

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

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

JSfiddle Demo

还有其他语言有这样的行为吗?如果是这样,那我肯定得改变我的习惯了..:)

我主要关心 PHP、C、C++、Java 和 ruby​​。

Today, while I was randomly reading the JavaScript patterns O'Reilly book, I found one interesting thing (page 27 for reference).

In Javascript, in some cases, there is a difference if the brace start location is different.

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

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

While

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

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

JSfiddle Demo

Does any other language out there have such behavior? If so, then I would have to change my habit for sure..:)

I am mainly concerned about PHP, C, C++, Java, and ruby.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

失与倦" 2025-01-10 18:16:20

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

>>> def foo():
...   return
...   { 1: 2 }
... 
>>> def bar():
...   return { 1: 2 }
... 
>>> foo()
>>> bar()
{1: 2}

您也许能够在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

从您提到的语言中,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

Any language that doesn’t rely on semicolons (but instead on newlines) to delimit statements potentially allows this. Consider Python:

>>> def foo():
...   return
...   { 1: 2 }
... 
>>> def bar():
...   return { 1: 2 }
... 
>>> foo()
>>> bar()
{1: 2}

You might be able to construct a similar case in Visual Basic but off the top of my head I can’t figure out how because VB is pretty restrictive in where values may be placed. But the following should work, unless the static analyser complains about unreachable code:

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

From the languages you mentioned, Ruby has the same property. PHP, C, C++ and Java do not simply because they discard newline as whitespace, and require semicolons to delimit statements.

Here’s the equivalent code from the Python example in Ruby:

>> def foo
>>   return { 1 => 2 }
>> end
=> nil
>> def bar
>>   return
>>   { 1 => 2 }
>> end
=> nil
>> foo
=> {1=>2}
>> bar
=> nil
困倦 2025-01-10 18:16:20

如果 JavaScript 解释器没有找到,它会自动在每一行的末尾添加一个 ; (有一些例外,这里不再赘述:)。

所以基本上问题不在于大括号的位置(这里代表对象文字,而不是大多数语言中的代码块),而是这个小“功能”迫使您的第一个示例 return ; = > 未定义。您可以查看 return ES5 规范

对于具有类似行为的其他语言,请查看 康拉德的回答

The JavaScript interpreter automatically adds a ; at the end of each line if it doesn't find one (with some exceptions, not getting into them here :).

So basically the issue is not the braces' location (which here represent an object literal, not a code block as in most languages), but this little "feature" that forces your first example to return ; => undefined. You can check out the behavior of return in the ES5 spec.

For other languages that have similar behavior, check out Konrad's answer.

后知后觉 2025-01-10 18:16:20

最肯定的是。 Google 的 go 编程语言表现出非常相似的行为(尽管效果不同)。正如那里所解释的:

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

..剪掉...

这种方法可以使代码看起来干净、无分号。令人惊讶的是,将 if 语句等构造的左大括号与 if 放在同一行非常重要;如果不这样做,在某些情况下可能无法编译或可能给出错误的结果。该语言在某种程度上强制使用大括号样式。

私下里,我认为罗布·派克只是想找个借口来要求使用“One True Brace Style”。

Most certainly. Google's go programming language exhibits a very similar behavior (albeit with different effects). As explained there:

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.

Secretly, I think Rob Pike just wanted an excuse to require the One True Brace Style.

浮萍、无处依 2025-01-10 18:16:20

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

return
{
     name: 'rajat'
};

是js引擎会在return;语句后插入一个分号(因此,返回undefined)。此示例是始终在右侧打开大括号且从不在左侧打开大括号的一个很好的理由。既然您已经正确地注意到,如果同一行中有一个大括号,解释器会注意到这一点并且无法插入分号。

The answer to that question is fairly easy. Any language that has "automatic semicolon insertion" might be in trouble on that line. The problem with this

return
{
     name: 'rajat'
};

..is that the js engine will insert a semicolon after the return; statement (and therefore, return undefined). This example is a good reason to open curly brackets always on the right side and never on the left side also. Since you already correctly noticed, if there is a curly bracket in the same line, the interpretator will notice that and can't insert a semicolon.

别挽留 2025-01-10 18:16:20

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)

FWIW, JSLint reports several warnings with that syntax:

$ 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)
我很OK 2025-01-10 18:16:20

我遇到的第一种语言是 awk (它也有一些语法“奇怪”;可选的分号、仅使用空格的字符串连接等等......)
我认为 DTrace 设计者(松散地基于 awk 的 D 语法)有足够的理智来不复制这些功能,但我一时想不起来。
一个简单的示例(在我的 Mac 上计算 DTD 中 ENTITY 标记的数量):

$ 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

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

$ 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
$ 

The first language where I came across this was awk (which also has its share of syntax "oddities"; optional semi colons, string concatenation using only whitespace and so on...)
I think the DTrace designers, which based the D syntax loosely on awk, had enough sense to NOT copy these features, but I can't remember off the top of my head.
A simple example (counting the number of ENTITY tags in a DTD, from my Mac):

$ 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

If this little script instead were written with the brace on a line of its own, this is what would happen:

$ 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
$ 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文