caller、callee是與javascript函數相關的兩個屬性,今天來總結下。javascript
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的屬性之一, 他指向擁有該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 這是咱們遇到的第二個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