尾递归优化流程解析
function tco(f) {
var value;
var active = false;
var accumulated = [];
return function accumulator() {
accumulated.push(arguments);
if (!active) {
active = true;
while (accumulated.length) {
// 用apply单纯是为了传入类数组,不用拆分
//等同于 var shifted = accumulated.shift(); value = f(...shifted);
value = f.apply(this, accumulated.shift())
//让顶层对象运用传进来的sum 方法,参数为,value一直到最后输出之前都是undefined
}
active = false;
return value;
}
};
}
var sum = tco(function(x, y) {
if (y > 0) {
return sum(x + 1, y - 1)
}
else {
return x
}
});
//tco返回一个accumulator函数,并通过这种方式将f传给accumulator
console.log(sum(1, 100)) //sum(1,100)等于运行了具有外部参数的accumulator(1,100)。参数是传给accumulator的。
// 101
具体流程解析
- sum获取一个返回的函数accumulator
var sum = tco(function(x, y) {
if (y > 0) {
return sum(x + 1, y - 1)
}
else {
console.log('shit')
return x
}
});
这一步tco(function)返回一个函数accumulator(),具有外部变量value,active,accumulated。 因为accumulator中有使用,所以这些外部变量没有销毁。
-
sum(1,100) 即调用accumulator(1,100)
-
向数组accumulated中push入arguments对象
accumulated.push(arguments);
-
此时active为false,进入if语句
-
active转为true, 然后进入while循环。 这一步很重要,之后每一次调用accumulator函数只会向accumulated数组中传参。而不会进入if语句, 而只有第一次while循环反复调用sum(x+1,y-1)到结束。
即进入这样一个循环 :
while (accumulated.length) {
value = f.apply(this, accumulated.shift())
sum(x+1,y-1) //即 accumulator(x+1,y-1)
accumulated.push(arguments)
}
一直到y=0时,sum(101,0)返回 101 ,不再向数组accumulated中传入数组,即离开循环。return 101 。