JavaScript中不同的语法错误表现不同

3

我不是 JavaScript 程序员,所以这可能是一个非常基础的问题。问题在于,当出现某些特定的语法错误时,整个 JS 代码都无法工作。

由于 JS 是解释型语言,我认为它应该独立地执行每一行,直到发生错误,但似乎并没有发生,至少在下面的情况下不是这样:

console.log('a')
consol.log('b')    //intentional typo in "console"
console.log('c')

---- output ----
a
ReferenceError: consol is not defined

上面的例子基于解释型语言的工作原理,听起来都很好。现在看一下以下错误:
console.log('a')
console.log('b'    //intentionally didn't put the right parenthesis 
console.log('c')

---- output ----
SyntaxError: missing ) after argument list

为什么第一行不应该被执行?

注意:我使用https://playcode.io运行代码,并在Mozilla Firefox上进行。


2
解析器必须在任何代码块运行之前将整个代码块翻译。换句话说,它不是逐行解析的。第一个错误不是语法错误,因为consol.log('b')语法上不是不正确的。 - Pointy
2
正如@Pointy所指出的那样,如果你来自一种编译语言,另一种思考它的方式是,第一个是运行时错误,第二个是编译错误。 - Keith
2
我在这个主题上并不是专家,但猜测现代浏览器在执行 JavaScript 之前会将其“解释”成另一种语言(更接近底层语言)。如果由于语法错误而无法解析脚本,则无法将脚本解释/解析为其他东西。 - Phil Cooper
@phil,“更接近底层”的意思(我猜你指的是JIT编译)通常只会在某些代码运行更频繁时发生,但是引擎确实会在运行之前将代码转换为AST。 - Jonas Wilms
1
@JonasWilms 是的,几乎所有的JavaScript引擎都是一样的。我是这么想的:如果你把这些代码输入到REPL中,第一行即使第二行有语法错误也会被执行。同样地,如果它是HTML页面中的两个不同的脚本标签,或者在runkit中的不同单元格中,或者... - Odalrick
显示剩余4条评论
4个回答

6

console不是语法错误,而是运行时错误。

语法定义了语言,让Javascript引擎理解你想要做什么。 console.log('b' console.log('c') 是无效语法,因为Javascript引擎无法确定在'b'console之间是否忘记了一些运算符,或者这些是否是单独的语句,或者你想做什么。

然而,consol.log()是一个完全有效的命令,假设在运行时存在名为consol的对象,可能在该行应该执行时存在,也可能不存在。只有在那时才能找出来。

Javascript总是解析和编译整个代码以构建可运行程序。这就是语法错误发生的地方。只有当整个代码的语法正确时,它才会执行该代码,这可能会产生或不产生运行时错误

由于JS是解释执行的,我认为它应该独立执行每一行代码。

"解释执行"与此无关。看这个例子:

while (foo) {
    bar();
}

显然在这里它无法独立执行每一行,因为这是一个复合结构。或者说:
foo();

function foo() {}

在执行foo()之前,需要解析并提升此function。但不,代码总是在运行时之前从上到下解析。


0

编译器是否认为第三行仍然是上一行的参数,因为您没有正确关闭括号?

例如,

console.log('a')
console.log('b',
console.log('c'))

这将是有效的代码。


0

JavaScript 的执行分为两个阶段。第一阶段,解释器会将整个代码转换成抽象语法树,并在环境记录中收集所有变量等。在此阶段,可能会发生早期错误,这意味着解析器无法理解您的代码。第二阶段是实际运行代码时,然后会出现运行时错误。


0
在第一个例子中,你本可以定义一个函数consol.log()。虽然你没有这样做,但它仍然能够被解析为函数调用。
在第二个例子中,浏览器无法解析它。封闭的(在语法上是不正确的。
简而言之,重要的是错误在解析器中的位置。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接