JavaScript中不同语法错误的不同行为

JavaScript中不同语法错误的不同行为,javascript,syntax-error,Javascript,Syntax Error,我不是JavaScript程序员,所以这可能是一个非常基本的问题。问题是,当出现一些特定的语法错误时,整个JS代码将无法工作 由于JS是解释的,我认为它应该独立执行每一行,直到错误发生,但它似乎没有发生,至少在下面的情况下是这样的: console.log('a') consol.log('b') //intentional typo in "console" console.log('c') ---- output ---- a ReferenceError: co

我不是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
为什么不执行第一行


注意:我曾经在Mozilla Firefox上运行过代码。

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

难道编译器不可能认为第3行仍然是上一行的参数,因为您没有正确地关闭括号吗

比如说,

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

将是有效代码。

consol
不是语法错误,而是运行时错误

语法定义了语言,使Javascript引擎理解您希望它做什么
console.log('b'console.log('c')
是无效语法,因为Javascript引擎无法判断您是否忘记了
'b'
console
之间的运算符,或者这些是单独的语句还是您想要的

但是,
consol.log()
是一个非常有效的命令,假设运行时存在名为
consol
的对象,在该行应该执行的时间点上,情况可能是这样,也可能不是这样。只有到那时您才会发现

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

因为JS是解释的,所以我认为它应该独立地执行每一行

“解释”与此无关。拿这个来说:

while (foo) {
    bar();
}
显然,它不能在这里独立执行每一行,因为这是一个复合结构。或者:

foo();

function foo() {}

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

在第一个示例中,您可以定义一个函数
consol.log()
。您没有,但仍然可以将其解析为函数调用

在第二种情况下,浏览器无法解析它。封闭的
在语法上不正确

简而言之,重要的是在解析器中的何处发现错误


解析器必须先翻译整个代码块,然后才能运行任何代码块。换句话说,它不会逐行分析。第一个错误不是语法错误,因为
consol.log('b'))
在语法上并不是不正确的。正如@Pointy指出的,如果你来自一种编译语言,另一种思考方式是,第一种是运行时错误,第二种是编译错误。我对这个问题不太在行,但我猜现在的浏览器会将javascript“解释”成另一种语言(更接近金属)执行之前。如果由于语法错误而无法解析脚本,则无法将脚本解释/解析为其他内容。@phil“更接近金属”一词(我猜您指的是JIT编译)如果某个代码运行得更频繁,通常会发生这种情况,但是是的,引擎会在运行它之前将代码转换为AST。@Jonaswillms是的,几乎所有JavaScript引擎都是一样的。我一般认为:如果在REPL中输入这些行,即使第二行出现语法错误,第一行也会被执行。同样,如果在html页面中有两个不同的脚本标记,或者在runkit中有不同的单元格,或者…