简体   繁体   English

为什么在行尾需要分号?

[英]Why is a semicolon required at end of line?

Why does this work: 为什么这样做:

a = []
a.push(['test']);
(function() {alert('poop')})()

But this gives the error "number is not a function": 但这给出了错误“数字不是函数”:

a = []
a.push(['test'])
(function() {alert('poop')})()

The only difference is the semicolon at the end of line 2. I've been writing JavaScript for a long time now. 唯一的区别是第2行末尾的分号。我已经写了很长时间的JavaScript了。 I know about automatic semicolon insertion, but I can't figure out what would be causing this error. 我知道自动分号插入,但我无法弄清楚会导致此错误的原因。

Take a look at this example of chained function calls. 看看这个链式函数调用的例子。

a.push(['test'])(function() {alert('poop')})()

Look familiar? 看起来熟悉? This is how the compiler/interpreter views your code. 这就是编译器/解释器查看代码的方式。

Detail 详情

Here is a portion of the grammar used to describe call expressions. 这是用于描述调用表达式的语法的一部分。

CallExpression : 
	MemberExpression Arguments 
	CallExpression Arguments 
	CallExpression [ Expression ] 
	CallExpression . IdentifierName

Essentially each group (...) is considered as Arguments to the original MemberExpression a.push . 基本上每个组(...)被视为原始MemberExpression a.push 参数

a.push (['test'])                // MemberExpression Arguments 
(function() {alert('poop')})     // Arguments  
()                               // Arguments 

Or more formally 或者更正式

CallExpression(
    CallExpression(  
        CallExpression(
            MemberExpression( a.push ),
            Arguments( (['test']) )
        ),
        Arguments( (function() {alert('poop')}) )
    ),
    Arguments( () )
)

I'm not a Javascript expert (or even a newbie :), but if you combine the second and third lines, it still looks syntactically valid: 我不是Javascript专家(甚至是新手:),但是如果你将第二行和第三行结合起来,它仍然看起来语法上有效:

a.push(['test'])(function() {alert('poop')})()

That's trying to treat the result of a.push(['test']) as a function, passing a function into it... and then calling the result as a function as well. 那是试图将a.push(['test'])作为一个函数处理,将函数传递给它...然后将结果作为函数调用。

I suspect that the semi-colon is required if the two statements can be syntactically combined into a single statement, but that's not what you want. 我怀疑如果两个语句可以在语法上合并为一个语句,则需要使用分号,但这不是你想要的。

Because 因为

a.push(['test'])(function() {alert('poop')})()

is a valid JavaScript expression. 是一个有效的JavaScript表达式。 And if some adjacent lines can be stick together to form a valid JavaScript expression, your JavaScript engine will stick them together. 如果某些相邻的行可以粘在一起形成一个有效的JavaScript表达式,那么您的JavaScript引擎会将它们粘在一起。

Though it is a valid JavaScript expression, a.push returns a number, which is not a function, and when you try to call something that is not a function, it returns the error you see. 虽然它是一个有效的JavaScript表达式, a.push返回一个不是函数的数字,当你尝试调用一个不是函数的东西时,它会返回你看到的错误。

a.push(['test']) will return the length of the array, a number. a.push(['test'])将返回数组的长度,一个数字。 Without a semicolon following, the compiler will then interpret the opening parentheses of self-invoking function following as if you're trying to execute that number as a function with arguments. 如果没有分号,编译器将解释自调用函数的开括号,就像您尝试将该数字作为带参数的函数执行一样。 Let's say it returned a length of 7, then essentially what is happening here is as if you wrote: 假设它返回的长度为7,那么基本上这里发生的事情就像你写的那样:

7 (function() {alert('poop')})();

Hence the error "number is not a function" because it doesn't know how to invoke 7 as a function. 因此错误“数字不是函数”,因为它不知道如何调用7作为函数。

There are cases where white space is not required as a token separator but only used to improve readability: 有些情况下,不需要空格作为令牌分隔符,但仅用于提高可读性:

White space characters are used to improve source text readability and to separate tokens (indivisible lexical units) from each other, but are otherwise insignificant. 空格字符用于提高源文本可读性并将标记(不可分割的词汇单元)彼此分开,但在其他方面无关紧要。 White space may occur between any two tokens […] but cannot appear within any other kind of token. 任何两个令牌之间可能会出现空白区域,但不能出现在任何其他类型的令牌中。

In this case the white space between a.push(['test']) and (function() {alert('poop')})() is not for token separator and thus insignificant. 在这种情况下, a.push(['test'])(function() {alert('poop')})()之间的a.push(['test'])不适用于令牌分隔符,因此无关紧要。 So it's equivalent to this: 所以它等同于:

a.push(['test'])(function() {alert('poop')})()

And since a references an empty array with the length 0, calling a.push(['test']) appends one element to a and returns the updated value of a.length , ie 1 : 并且由于a引用空数组与长度为0,调用a.push(['test'])附加一个元件到a ,并返回更新后的值a.length ,即1

1(function() {alert('poop')})()

And the rest is history. 剩下的就是历史。

a.push(['test']) returns a number. a.push(['test'])返回一个数字。

You then attempt to call the number as a function with function() {alert('poop')} as the only argument. 然后,您尝试将该数字作为函数调用, function() {alert('poop')}作为唯一参数。

Hence your error, number is not a function . 因此你的错误, number is not a function

The result of a.push() is the size of the returned array, in this case, 1. The enclosing parentheses around your function make the Javascript parser think that you're trying to call: a.push()的结果是返回数组的大小,在本例中为1.围绕函数的括号使得Javascript解析器认为您正在尝试调用:

1( function() {alert('poop')} )()

Or that you're trying to call a function called 1 with an anonymous function as a parameter, then execute the return as a function. 或者您尝试使用匿名函数作为参数调用名为1的函数,然后将return作为函数执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM