2012年12月23日 星期日

callee and caller

簡介一下callee與caller
  • callee為function arguments的一個操作,用來代表function本身
  • caller為function呼叫者,若為最上層呼叫
下面是簡單的操作,將callee與caller的值列印出來:

由fn2操作fn1,最上層呼叫直接呼叫fn2

function fn1(){
  console.log('>>fn1');
  console.log('my callee:'+arguments.callee);
  console.log('my caller:'+fn1.caller);
}
function fn2(){
  console.log('>>fn2');
  fn1();
}
fn2();

執行結果:
# node test 
>>fn2
>>fn1
my callee:function fn1(){
  console.log('>>fn1');
  console.log('my callee:'+arguments.callee);
  console.log('my caller:'+fn1.caller);
}
my caller:function fn2(){
  console.log('>>fn2');
  fn1();
}


如果想要測試最上層直接呼叫fn1的狀況,修改程式碼如下:

function fn1(){
  console.log('>>fn1');
  console.log('my callee:'+arguments.callee);
  console.log('my caller:'+fn1.caller);
}
fn1();

則結果為:
# node test
>>fn1
my callee:function fn1(){
  console.log('>>fn1');
  console.log('my callee:'+arguments.callee);
  console.log('my caller:'+fn1.caller);
}
my caller:function (exports, require, module, __filename, __dirname) { function fn1(){
  console.log('>>fn1');
  console.log('my callee:'+arguments.callee);
  console.log('my caller:'+fn1.caller);
}
fn1();

}

其中callee的應用,可以用在loop的程式中,強迫程式同步進行...
ex:
var count = 5;
process.nextTick(function fn1(){
  count --;
  console.log('>>fn1, ts=%s, count=%s', new Date().getTime(), count);
  if(count > 0) process.nextTick(arguments.callee);
});

執行結果:
# node test 
>>fn1, ts=1356282477274, count=4
>>fn1, ts=1356282477280, count=3
>>fn1, ts=1356282477281, count=2
>>fn1, ts=1356282477281, count=1
>>fn1, ts=1356282477281, count=0

這邊的output就可以看得出來function fn1會依序被執行,如果有非同步動作,則可以在callback中使用同樣手法讓程序變成循序執行的...

另外,caller的應用,直覺想到的是debug...
寫個簡單的log程式如下,希望可以記錄錯誤是由哪個function發出來的:
var log = {
  info: function fn(msg){
    console.log("Call from [%s]: %s", fn.caller.name , msg);
  }
}
function doSomething() {
  log.info('test');
}
doSomething();


執行結果:
node test
Call from [doSomething]: test