[转载]caller 和 callee

转载来源:https://www.cnblogs.com/mydia/p/7494720.html

caller 以及 callee是比较少见的属性,可能才了解前端的童鞋都认识。

callee是arguments的属性,值为调用该参数的函数(即是该函数)。

function apple () {
    console.log(arguments.callee) // apple();
}

caller是function的属性,值为调用该函数的函数(若函数为顶层函数,则返回null)。

function banana () {
    apple();
}
function apple () {
    console.log(apple.caller) // banana()
}

这两个属性用的越来越少,一方面是因为函数本身的属性应用场景少,例如name,length,constructor,另一方面,es6箭头函数的推出,让箭头函数不再持有arguments与caller。在es6中使用,会产生如下错误信息,提示是受限的属性。

'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.

严格模式中也无法使用arguments,且当函数为匿名函数的时候,callee返回undefined。

我只说下个人对于这两个属性的应用的小小见解。

callee
在递归中,如下

function factorial(n, total) {
    if (n === 1) return total;
    return factorial(n - 1, n * total);
}

factorial(5, 1) // 120

这个函数中 factorial 在函数体内也出现,通俗地说就是如果我要修改函数名,需要修改两处。如果用下面的方式就只用修改一次。

function factorial(n, total) {
    if (n === 1) return total;
    return arguments.callee(n - 1, n * total);
}

caller
这个可以查看函数的调用链,如下:

function main () {
    apple();
}
function orange() {
    watermelon()
}
function watermelon() {
    peach()
}
function grape() {
    lemon()
}
function lemon() {
    summary();
}
function peach() {
    grape();
    // console.log(arguments.callee.caller.name);
}
function apple() {
    orange();
}
function summary() {
    let arg = arguments.callee;
    let arr = [arguments.callee.name];
    function _summary(a) {
        if(a.caller) {
            arr.unshift(a.caller.name.toString());
            _summary(a.caller);
        } else {
            console.log(arr.join('->'))
        }
    }
    return _summary(arg);
}
console.log(main())

结果为

main->apple->orange->watermelon->peach->grape->lemon->summary

加一点场景,更好理解,例如,李太太出门买水果(main),买了一个后买另一个,到家后开始结算(summary),忘记了自己买水果的顺序,那么上列的结果就阐明了买水果的顺序。

posted @ 2020-08-16 14:09  风の住む街  阅读(83)  评论(0)    收藏  举报