Function.caller、arguments.caller、argument.callee


caller、callee是與javascript函數相關的兩個屬性,今天來總結下。

Function.caller

caller是javascript函數的一個屬性,它指向調用當前函數的函數,如果函數是在全局范圍內調用的話,那么caller的值為null。

function outer() {
    inner();
}
function inner() {
    if(inner.caller==null) { //值為null,在全局作用域下調用
        console.log("我是在全局環境下調用的");
    } else {
        console.log(inner.caller+"調用了我");
    }    
}
inner();
outer();

arguments.callee

arguments是函數內部中一個特殊的對象,callee是arguments的屬性之一, 他指向擁有該arguments的函數對象。在某些不方便暴露函數名的情況下, 可以用arguments.callee代替函數名。但是,在嚴格模式(“use strict;”)下訪問arguments.callee會拋出 TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them 錯誤

現在我們來仔細看看上面那段代碼。如果老板說:“不行,函數名叫inner不好聽,給我改!” 改代碼容易,但是想改了后不出錯誤那可就難了。 這時我們就可以使用argument.callee來代替函數名,減少修改代碼的地方,從而降低出錯率

function outer() {
    inner();
}
function inner() { //只需改這個函數名,而不需要改內部代碼
    if(arguments.callee.caller==null) {
        console.log("我是在全局環境下調用的");
    } else {
        console.log(arguments.callee.caller+"調用了我");
    }    
}
inner();
outer();

除此之外,當我們寫遞歸函數時,也會在函數里面暴露函數名,此時也會產生問題,如下。

/**
 * factorial:階乘
 */
function factorial(n) {
    if(n<=1) {
        return 1;
    } else {
        return n*factorial(n-1);
    }
}
console.log(factorial(3)); //6
var foo = factorial;
console.log(foo(3)); //6
factorial = null; 
console.log(foo(3)); //Error:factorial is not a function

factorial置為null,雖然foo指向了factorial使其不會被銷毀, 但是原函數內部的函數名任然是factorial,自然應找不到而報錯。 此時我們就可以用arguments.callee代替函數名

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

那還能不能更強點?畢竟arguments.callee在嚴格模式下是無法訪問的,肯定沒法兒用啊!

var factorial = (function foo(n) {
    if(n<=1) {
        return 1;
    } else {
        return n*foo(n-1); //內部可訪問foo
    }
});
foo(6); //ReferenceError: foo is not defined

以上代碼利用命名函數表達式的形式創建了一個遞歸函數。 這有兩個好處:第一,嚴格模式下函數任然能照常運轉; 第二,性能優於argument.callee。注意foo僅在其函數體內可訪問,在外是訪問不到的。

arguments.caller

arguments.caller 這是我們遇到的第二個caller,沒啥用,在嚴格模式下無法訪問,非嚴格模式下值也為undefined,而且貌似被廢棄了

總結

1.Function.caller指向調用該函數的函數

2.arguments.callee指向擁有該arguments的函數

3.arguments.caller沒啥用

引用

1.《javascript高級程序設計》

2.MDN

  2.1 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/caller

  2.2 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller

  2.3 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments/callee


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM