Page 271 - 你不知道的JavaScript(下卷)
P. 271
};
})();
foo( 123456 ); // 3810376848.5
如果你在实现了 TCO 的 ES6 引擎中运行前面的代码,会得到如前显示的 3810376848.5。
然而,它在非 TCO 引擎里仍然会因 RangeError 而失败。
7.7.2 非 TCO 优化
还有几种其他技术可以用来重写代码,使得不需要每次调用时都增长栈。
其中一种这样的技术叫作 trampolining,它相当于把每个部分结果用一个函数表示,这些
函数或者返回另外一个部分结果函数,或者返回最终结果。然后就只需要循环直到得到的
结果不是函数,得到的就是最终结果。
考虑:
"use strict";
function trampoline( res ) {
while (typeof res == "function") {
res = res();
}
return res;
}
var foo = (function(){
function _foo(acc,x) {
if (x <= 1) return acc;
return function partial(){
return _foo( (x / 2) + acc, x - 1 );
};
}
return function(x) {
return trampoline( _foo( 1, x ) );
};
})();
foo( 123456 ); // 3810376848.5
这个重写需要最小的改动来把递归转化为 trampoline(..) 中的循环。
(1) 首先,把 return _foo .. 一行封装在 return partial() { .. 函数表达式中。
(2) 然后,把 _foo(1,x) 调用封装在 trampoline(..) 调用中。
这个技术不限制调用栈的原因是,每个内部的 partial(..) 函数只是返回到
trampoline(..) 的 while 循环中,trampolining 运行函数并进行下一次的循环迭代。换句话
248 | 第 7 章
图灵社区会员 avilang(1985945885@qq.com) 专享 尊重版权