为什么嵌套一堆块会导致JavaScript中的堆栈溢出
代码为什么嵌套一堆块会导致JavaScript中的堆栈溢出,javascript,stack-overflow,Javascript,Stack Overflow,代码{}在JavaScript中是完全合法的,因为它代表一个 然而,我注意到在另一个Chrome*中嵌套大量块({{…}}): 未捕获范围错误:超过最大调用堆栈大小 为什么这里会发生堆栈溢出 下面是一个例子来说明这个问题(JSFIDLE崩溃) 在JSRoom中询问时发现,在chrome和Firefox上,魔法数字分别为3913和2555 什么被推到堆栈中?为什么? (*)我已经检查过了,IE和Firefox中也出现了这种情况 更新:我已经检查了IE是否能够避免堆栈溢出异常。它投掷了两次,但第
{}
在JavaScript中是完全合法的,因为它代表一个
然而,我注意到在另一个Chrome*中嵌套大量块({{…}}
):
未捕获范围错误:超过最大调用堆栈大小
为什么这里会发生堆栈溢出
下面是一个例子来说明这个问题(JSFIDLE崩溃) 在JSRoom中询问时发现,在chrome和Firefox上,魔法数字分别为3913和2555 什么被推到堆栈中?为什么?
(*)我已经检查过了,IE和Firefox中也出现了这种情况 更新:我已经检查了IE是否能够避免堆栈溢出异常。它投掷了两次,但第三次没有。如果任何读者都有IE,并且愿意测试它的旧版本(如IE8和IE9),并让我知道发生了什么,我将非常感激。的默认实现虽然简单而优雅,但只使用一种方法解析每种语言的语法规则。这些方法递归调用其他方法,因此当嵌套规则过多时,它会超出堆栈大小。Chrome和Firefox都使用这种解释器实现 您会注意到,许多“+”虽然与范围无关,但会导致相同的异常:
+ + + + + + + + + ... // same error
首先,戈德是完全正确的。这是由解析器的递归性质造成的,所以请给他投票表决。但证据需要证明,OP希望我将此作为一个单独的答案发布 火狐 那么,到哪里去了解它是如何完成的呢?问一些正在制造引擎的人。所以我转到了
上的#jsapi
频道irc://irc.mozilla.org
并询问他们:
zirak:well,使用递归下降解析器,所有的结果将大致对应于C堆栈上的一个帧
zirak:解析器位于js/src/front/parser.cpp
zirak:Parser::statement(bool-canHaveDirectives)和Parser::statements()差不多
zirak:在这种情况下,递归将是Parser::blockStatement->Parser::statements->Parser::statement->Parser::blockStatement->Parser::statement->Parser::blockStatement
这几乎就是答案。前往mozilla中央存储库并深入挖掘,我们有了嫌疑犯:
调用statements
,解析块以查找另一个块,调用blockStatement
调用statements
,解析块以查找另一个块,调用blockStatement
调用statements
,解析块以查找另一个块,调用blockStatement
parser
的文件。果然,它就在那儿
下一件事是在解析块时查找,因此我天真地搜索了语句
,找到了有希望的结果
今天是我们的幸运日,一个巨大的开关!这就是我们所关心的,一个调用ParseBlock
,另一个有前途的名字
实际上,toParseStatement
。因此,明确地说,我们有两个功能:
调用ParseStatement
,该语句解析块,以查找另一个块,调用ParseBlock
调用ParseStatement
,该语句解析块,以查找另一个块,调用ParseBlock
调用ParseStatement
,该语句解析块,以查找另一个块,调用ParseBlock
它调用parseSourceElements
它调用parseStatement
,它解析块,找到另一个块,调用parseBlockStatement
它调用parseSourceElements
它调用parseStatement
,它解析块,找到另一个块,调用parseBlockStatement
它调用parseSourceElements
它调用parseStatement
,它解析块,找到另一个块,调用parseBlockStatement
如果浏览器没有崩溃,这是一个有趣的问题,但这个答案不可能给出答案。@faffafff为什么会创建堆栈帧,因为它不是一个可能的作用域?@faffaff Javascript没有块作用域。@Paulpro这几乎是正确的。JavaScript确实有块作用域,但仅在
try/catch
和with
中。如果将足够多的表达式传递给逗号运算符,则还会出现堆栈溢出错误(请参阅)。有事告诉我们