javascript中caller與callee的作用以及用法
這兩個關鍵字在平時編碼中幾乎難以用到,但它們既然存在於javascript語言體系中,那麼還是有必要了解下。
caller是javascript函數類型的一個屬性,它引用調用當前函數的函數
function func() {
alert(func.caller);
}
function func1() {
func();
}
func1();
比如上面的代碼, 因爲func函數是杯func1函數調用的, 所以func函數中對caller的引用就是func1函數。如果func函數直接在頂層的javascript環境中被調用,那麼caller將返回null。
我們可以利用caller的特性跟蹤函數的調用鏈
function func() {
let caller = func.caller;
while(caller != null) {
console.log(caller.name);
caller = caller.caller;
}
}
function func1() {
func();
}
function func2() {
func1();
}
function func3() {
func2();
}
func3();
以上代碼將func3到func的函數調用鏈打印出來。
callee則不是函數對象的屬性,它是函數上下文中arguments對象的屬性
function func() {
alert(arguments.callee);
}
它引用的是函數自身,在上面的代碼中,arguments.callee引用的就是func函數本身。既然他引用的是函數本身,那麼似乎顯得有點多餘,當我們需要在函數體內使用函數本身時,直接通過函數名調用就可以了,幹嘛還要多此一舉的通過arguments.callee這樣去調用。然而我覺得callee存在的意義可能是想解耦函數本身對函數名稱的依賴吧, 比如說在遞歸的環境下,函數內部通常還要調用函數本身, 而調用函數本身就免不了硬編碼函數名稱, 如果函數名稱有變化, 那麼函數中的代碼也需要修改,使用callee就可以避免此類情況。
function factorial( num ) {
if( num == 1 ) {
return 1;
}
let result = num * factorial(num - 1);
return result;
}
alert(factorial(100));
上面的階乘函數通過callee可以改造成
function factorial( num ) {
if( num == 1 ) {
return 1;
}
let result = num * arguments.callee(num - 1);
return result;
}
alert(factorial(100));
如此同樣實現遞歸, 但是可以做到函數體不依賴函數名稱。