前言
javascript中的caller和callee一眼望过感觉是一样的,然而一个字母的区别在应用中却天差地别。字面意思caller直接翻译为调用者,callee翻译为被召者。那么这两个到底是什么?怎么用?是我们本文的重点。
1. callee
在了解callee之前我们先了解函数内部arguments这个特殊的属性。arguments是一个类数组对象,它包含着所有传入函数中的参数。这也让我们明白了 arguments的主要用途就是保存函数参数。这个对象有一个名叫做callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
function testArguments(num,type){
console.log(arguments);
console.log(arguments[0],arguments[1]);
}
testArguments(10,'前端callee')

function factorial(num){
if(num === 1){
return 1;
}else{
return num * factorial(num - 1);
}
}
console.log(factorial(5));
//通常如果能保证函数名不变化,我们可以这下写,函数内部和函数通过factorial耦合在意一起,一旦函数名重新定义这个函数返回结果将不再是我们想要的结果。
var testFactorial = factorial;
console.log(testFactorial(5)); //120
factorial = function(){
return 0
};
console.log(testFactorial(5));//0
console.log(factorial(5));//0
为了消除这种耦合我们可以使用 arugments.callee这时候我们的函数可以变成如下实例:
function factorial(num){
if(num === 1){
return 1;
}else{
return num * arguments.callee(num - 1);
}
}
重写后的函数体中没有函数名,无论引用的函数使用任何名称时,都能保证递归的正常调用。
2.caller
ECMAScript 5也规范化了另一个函数对象的属性caller。这个属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为 null。
function outer() {
inner();
}
function inner() {
console.log(inner.caller)
}
outer();
// 打印结果结果就是outer函数本尊,为了实现更松散耦合,我们可以将inner.caller改为arguments.callee.caller.
不难看出caller可以认为那个函数调用了它,它就指向谁,如果是函数是通过window调用,这值为null。此时我们再看看图一中的这个属性。
