Function.caller、arguments.caller、argument.callee

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

Function.caller

caller是javascript函數的一個屬性,它指向調用當前函數的函數,若是函數是在全局範圍內調用的話,那麼caller的值爲null。java

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();

除此以外,當咱們寫遞歸函數時,也會在函數裏面暴露函數名,此時也會產生問題,以下。spa

/**
 * 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在嚴格模式下是沒法訪問的,確定無法兒用啊!code

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,並且貌似被廢棄了blog

總結

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

相關文章
相關標籤/搜索