从前有匹马叫代码
心若没有栖息的地方,到哪里都是流浪

在读 《深入理解ES6》一书中,看到有关函数的 “尾调用优化” 章节,特此记录一下

尾调用 指的是 函数作为另一个函数的最后一条语句被调用:

function foo () {
    return bar();  
}

书中说 在 ES5 的时候,尾调用的实现与其他函数调用类型,创建一个新的帧栈,然后将它推入调用栈表示调用,也就是说在循环调用中,每个未执行完的帧栈都保存在内存中,当调用栈变的过大会造成性能问题.

ES6 的优化

严格模式下,缩减了尾调用栈的大小;非严格模式不受影响,如果满足以下条件,尾调用不再创建新的帧栈,而是服用当前帧栈.

  1. 尾调用不访问当前帧栈的变量(非闭包)

  2. 在函数内部,尾调用是最后一条语句

  3. 尾调用的值作为结果返回

看如下例子:

// 可以优化

"use strict";
function foo() {
    return bar();
}
// 无法优化 -> 函数调用没有作为值返回;

function foo() {
    bar();
}
// 无法优化 -> 此处 函数并没有直接被返回,而是执行了一步操作
"use strict";

function foo() {
    return 1 + bar();    
}
// 无法优化 -> 调用不在尾部

function foo() {
    var result = bar();
    return result;
}
// 无法优化,闭包!

"use strict";

function foo() {
    var num = 1,
          getNum = () => num;
    return getNum();
}

因为尾调用优化是执行在JS 引擎上的优化,在我们实际的开发中的应用场景是什么呢?

场景1: 获取一个固定格式的日期

function getDate() {
    return createDateTime(true);  
}


function getTime() {
    return createDateTime(false);
}


function createDateTime(date) {
    // ...
    return date ? 'YY-MM-DD':'YY-MM-DD hh:mm:ss'    
}

场景2:递归

function factorial(n,p=1) {
    if(n <= 1) {
        return n*p;
    }else {
        let result = n * p;
        return factorial(n-1,result);
    }  
}

 

posted on 2021-10-24 22:09  从前有匹马叫代码  阅读(34)  评论(0编辑  收藏  举报