JavaScript和尾部调用
JavaScript and Tail Call
根据v8票证,它说
尾部调用消除与JavaScript不兼容,因为它在实际中使用世界考虑以下内容:
function foo(x) {
return bar(x + 1);
}
function bar(x) {
return foo.arguments[0];
}
foo(1)
返回1。
它没有清楚地解释如果JavaScript支持tail调用,那么foo(1)的值是什么,为什么?
有人能解释吗?
这值得一点解释。对话开始时是这样的(代码重新格式化):
如果我在Chrome中打开JavaScript控制台并写下以下内容:
function fac(n, a) { if (n == 0) { return a; } else { return fac(n - 1, a * n); } } fac(100000, 1);
我得到这个:范围错误:最大调用堆栈大小超过
我认为V8可能是其他编程的一个很好的目标虚拟机语言,如果它支持尾部调用。这是我能看到的唯一一个大障碍适用于具有函数功能的语言。
如果测试代码,您会注意到fac
适用于低值,返回Infinity
用于更高的值,并导致浏览器抛出RangeError
(超过最大调用堆栈大小)用于更高值。
原因是从另一个函数中调用的每个函数都被添加到"调用堆栈"中,这涉及到一些内存开销。如果有足够的递归,环境将耗尽内存。
这在其他语言中是通过"尾部调用消除"或消除将调用添加到调用堆栈的需要来实现的。例如,类似函数的东西可能存在,与正常函数不同的是,当它们返回时,会导致调用函数返回。这可以消除添加到调用堆栈的需要,这意味着递归本质上可以是无限的。有关详细解释,请参阅维基百科上的尾注文章。
对上面消息的响应只是提供了尾部调用消除(从调用堆栈中删除函数)与其他功能(Function#arguments)
(启用非标准功能)不兼容的原因。
它没有清楚地解释如果JavaScript支持尾部调用会是foo(1)的值,为什么?
执行foo(1)
时,该值将为1
,因为foo
函数返回bar
函数的结果,而bar
函数除了用foo.arguments[0]
读取foo
函数的第一个参数外什么也不做(arguments
是每个函数可用的隐含对象,用于读取传递给函数的参数)并返回它。当你这样做时,foo
的第一个自变量恰好是1
:
foo(1);
以下是分解:
function foo(x) {
return bar(x + 1); // foo calls bar function which returns 1
}
function bar(x) {
return foo.arguments[0]; // bar reads first argument passed to foo which is 1
}
foo(1); // 1 is x in foo function
bar
函数只读取foo
的第一个参数(通过foo.arguments[0]
)并返回它,因此不进行加法运算。
需要明确的是,尾部调用消除是一种节省堆栈空间的优化技术,对递归特别有用。当一个函数以对另一个函数的调用结束时,尾部调用消除可以避免分配另一个堆栈帧来调用被调用的函数。相反,它将重用(销毁并重新调整用途)调用函数的堆栈帧,因为(可能)不再需要它。然而,该示例显示JavaScript代码可能仍然需要调用方的堆栈框架。
它没有清楚地解释如果JavaScript支持尾部调用会是foo(1)的值,为什么?
如果支持尾部调用消除,则在对bar
进行尾部调用时,有关foo
调用的信息将被销毁,因此foo.arguments[0]
将是一个错误。如果给定的代码要工作,那么尾调用消除是不可能的。
- 如何使jQuery插件函数可调用以供独立使用,而不在集合上操作
- D3在一个调用中绘制不同的SVG形状,没有可见性
- 如何从Java/scala调用js美化程序
- 如何调用这个匿名 JavaScript 函数
- 如何从模块链中调用函数.导出到节点中
- 我需要从php调用javascript或jquery
- Chrome开发工具(如何知道我在调用哪个javascript对象)
- 单击按钮后如何逐个调用分区,上一个分区将隐藏
- 另一个ajax调用中的Jquery ajax调用在for循环中没有按预期工作
- Twitter Bootstrap typeahead:使用“this”获取上下文/调用元素
- JavaScript尾部调用中的函数是否经过优化
- 什么'这是“_函数:while“;Babel.js尾部调用中的语法
- 在 JavaScript 中封装尾部调用优化的实用程序
- 用被调用者的尾部调用函数'的参数列表
- JavaScript和尾部调用
- 是否可以在WebKit中检测尾部调用优化
- 不能在节点v6.4.0中启用尾部调用优化
- 如何在ES5中对递归匿名函数应用TCO(尾部调用优化)?
- 为什么没有javascript引擎支持尾部调用优化?
- Node.js尾部调用优化:可能与否