callee和caller
阿新 • • 發佈:2019-01-30
在之前的文章中我說到了arguments,現在來說一下他的屬性callee和一個長得相似的雙胞胎弟弟caller:
首先說callee,來一段程式碼:
var a=function(){
console.log(arguments.callee);
}
var b=function(){
a()
}
b();
這段程式碼在chrome中輸出的是:
ƒ (){
console.log(arguments.callee);
}
這個函式和a函式是不是一模一樣?
callee返回正在執行的函式本身的引用。callee是arguments的一個屬性,這個屬性是一個指標,指向這個擁有arguments 物件的函式,(arguments是呼叫函式,那麼這個callee就是呼叫函式的啦)
首先我們來說一個用callee解決的例子,階乘的計算:
function factorial(num){
if(num<=1){
}else{
return num*factorial(num-1);
}
}
上面的程式碼是用的是函式名。上述方法會增強耦合性,為了降低耦合性我們就用callee,而且無論引用函式的時候是什麼名字都可以完成遞迴呼叫。看看callee:function factorial(num){ if(num<=1){ return 1; }else{ return num*arguments.callee(num-1); } }
caller:和他相似的我們還有一個caller,es5中規範化了另外一個函式物件屬性caller;這個屬性中儲存著呼叫當前的函式的函式引用,如果是全域性作用於中呼叫當前的函式就返回null
function outer(){
inner();
}
function inner(){
1. alert(arguments.callee.caller);
2. alert(inner.caller)
//上面的這兩行是一樣的1比2 的耦合性更鬆散
3. alert(arguments.caller);//undefined
// 3.這行程式碼在嚴格模式下會報錯,但是非嚴格模式下就是undefined
}
outer();
// 說是定義argumnets.callee屬性是為了分清qrguments.caller和caller
// 屬性嚴格模式下不能為caller屬性賦值,不然報錯
// var a=function(){
// alert(a.caller);
// }//定義一個函式。裡面輸出a.caller
// var b=function(){
// a();
// }//定義一個函式呼叫那個a函式;
// b();//輸出b函式。
上面的例子中,是呼叫的b根據caller的特性就知道了答案。
// var a=function(){
// alert(a.caller);
// }//定義一個函式。裡面輸出a.caller
// var b=function(){
// a();
// }//定義一個函式呼叫那個a函式;
// a();//null(a在任何函式中被呼叫,即為頂層函式,輸出的就是null),上面的例子一中,a函式是在b中呼叫的所以不是頂層不反悔null,返回當前的呼叫就是b函式啦,而這個例子是在全域性中呼叫的自然是null
最後一個例子幫助深刻地理解頂層:要是a中也有了一個函式
var c=function(){
alert(c.caller);
}
var a=function(){
c()
alert(a.caller);
}
var b=function(){
a();
}
a();
這個例子在c中的alert出來的是a函式,原因是在a中呼叫。a中alert出來的是null,畢竟你是在全域性中呼叫的a的函式。b函式相當於沒有用。
好了,這麼多例子都不懂的話,可能是我寫的太差吧。