Javascript - 全面理解 caller,callee,call,apply

longwansheng發表於2007-12-04
http://www.zzbang.cn/html/dev/js/2007/11/09/50/[@more@]

1、caller

JScript參考中說明為:返回一個對函式的引用,該函式呼叫了當前函式。如何理解這句話, 先來舉個簡單的例子:
// caller demo {function callerDemo() {	if (callerDemo.caller) {		var a= callerDemo.caller.toString();		alert(a);	} else {		alert("this is a top function");	}}function handleCaller() {	callerDemo();}  
上面的例子,可以看出,它就是返回一個呼叫資料的引用。(指向請求呼叫的函式) 也由此可以看出,當在這樣的情況下,

2、callee

JScript參考中的說明為:返回正被執行的 Function 物件,也就是所指定的 Function 物件的正文。
需要注意的是callee擁有length屬性,這個在有的時候用於驗證還是比較好的。
function calleeDemo() {	alert(arguments.callee);}function calleeLengthDemo(arg1, arg2) {	if (arguments.length==arguments.callee.length) {		window.alert("驗證形參和實參長度正確!");		return;	} else {		alert("實參長度:" +arguments.length);		alert("形參長度: " +arguments.callee.length);	}}		
從上面的例子可以看出,callee可以用來打在執行函式,也就是指向被呼叫的函式。上面的例子就說明calee可以列印其本身,當然還有其它的一些用途。而length屬性中arguments.length是實參長度,arguments.callee.length是形參長度,由此可以判斷呼叫時形參長度是否和實參長度一致。

3、call 和 apply

call方法JScript參考中的說明:呼叫一個物件的一個方法,以另一個物件替換當前物件。call([thisObj[,arg1[, arg2[, [,.argN]]]]]),但是沒有示例
apply方法JScript參考中的說明:應用某一物件的一個方法,用另一個物件替換當前物件。apply([thisObj[,argArray]])
實際上這兩個的作用幾乎是相同的,要注意的地方是call(thisObj[,arg1[, arg2[,)中的arg引數可以是變數,而apply([thisObj[,argArray]])中的引數為陣列集合。下面來看看call, apply的具體應用
// simple call demofunction simpleCallDemo(arg) {	window.alert(arg);}function handleSPC(arg) {	simpleCallDemo.call(this, arg);}// simple apply demofunction simpleApplyDemo(arg) {	window.alert(arg);}function handleSPA(arg) {	simpleApplyDemo.apply(this, arguments);}	
從上面簡單的例子可以看出,call和apply可以把當前的引數傳遞給另外一個函式的引數中,從而呼叫另一個函式的應用。有的時候這是一個很實用的方法,當然,用call或是apply(是引數或是陣列),看實際情況而定了。

下面來看另一個應用

call和apply還有一個技巧在裡面,就是用call和apply應用另一個函式(類)以後,當前的函式(類)就具備了另一個函式(類)的方法或者是屬性,這也可以稱之為“繼承”。看下面示例。
// inheritfunction base() {	this.member = "never-online";	this.method = function() {		window.alert(this.member);	}}function extend() {	base.call(this);	window.alert(member);	window.alert(this.method);}	
上面的例子可以看出,透過call之後,extend可以繼承到base的方法和屬性。

再看一個apply的應用

// advanced apply demofunction adApplyDemo(x) {	return ("this is never-online, BlueDestiny '" + x + "' demo");}function handleAdApplyDemo(obj, fname, before) {  var oldFunc = obj[fname];  obj[fname] = function() {    return oldFunc.apply(this, before(arguments));  };}function hellowordFunc(args) {  args[0] = "hello " + args[0];  return args;}function applyBefore() {	alert(adApplyDemo("world"));}function applyAfter() {	handleAdApplyDemo(this, "adApplyDemo", hellowordFunc);	alert(adApplyDemo("world")); // Hello world!}	
需要注意的是,要先點"原始的adApplyDemo('world')"按鈕,如果先點"應用後的adApplyDemo('world')"按扭,會先應用了apply方法,這樣原始的值將會被改變。或許有的朋友沒有發現有什麼特別的,我在這裡指明一下,當點選左邊的按扭時,只有"this is never-online, BlueDestiny 'world' demo", 當點選右邊的按扭後,會現結果是"this is never-online, BlueDestiny 'hello world' demo",再點點左邊的按扭,看看結果又會是什麼呢?自己試試看:D,已經改寫了函式adApplyDemo。這個例子則說明了call和apply的“真正”作用了。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/92289/viewspace-988434/,如需轉載,請註明出處,否則將追究法律責任。

相關文章