javascript的call,callee,calle,apply

call 方法
請參閱
應用於:Function 對象
要求
版本 5.5
調用一個對象的一個方法,以另一個對象替換當前對象。

call([thisObj[,arg1[, arg2[, [,.argN]]]]])
參數
thisObj
可選項。將被用作當前對象的對象。
arg1, arg2, , argN
可選項。將被傳遞方法參數序列。
說明
call 方法可以用來代替另一個對象調用一個方法。call 方法可將一個函數的對象上下文從初始的上下文改變爲由 thisObj 指定的新對象。

如果沒有提供 thisObj 參數,那麼 Global 對象被用作 thisObj。

-------------------------------------------------------------------------------------------
乍一看,很容易把人看迷胡,先做一些簡單的說明
obj1.method1.call(obj2,argument1,argument2)
如上,call的作用就是把obj1的方法放到obj2上使用,後面的argument1..這些做爲參數傳入.

舉一個具體的例子
f
unction add(a,b)
{
alert(a+b);
}
function sub(a,b)
{
alert(a-b);
}

add.call(sub,3,1);


這個例子中的意思就是用 add 來替換 sub,add.call(sub,3,1) == add(3,1) ,所以運行結果爲:alert(4); // 注意:js 中的函數其實是對象,函數名是對 Function 對象的引用。


看一個稍微複雜一點的例子

function Class1()
{
this.name = "class1";

this.showNam = function()
{
alert(this.name);
}
}

function Class2()
{
this.name = "class2";
}

var c1 = new Class1();
var c2 = new Class2();

c1.showNam.call(c2);

注意,call 的意思是把 c1 的方法放到c2上執行,原來c2是沒有showNam() 方法,現在是把c1 的showNam()方法放到 c2 上來執行,所以this.name 應該是 class2,執行的結果就是 :alert("class2");

怎麼樣,覺得有意思了吧,可以讓a對象來執行b對象的方法,這是java程序員所不敢想的。還有更有趣的,可以用 call 來實現繼承

function Class1()
{
this.showTxt = function(txt)
{
alert(txt);
}
}

function Class2()
{
Class1.call(this);
}

var c2 = new Class2();

c2.showTxt("cc");

這樣 Class2 就繼承Class1了,Class1.call(this) 的 意思就是使用 Class1 對象代替this對象,那麼 Class2 中不就有Class1 的所有屬性和方法了嗎,c2 對象就能夠直接調用Class1 的方法以及屬性了,執行結果就是:alert(“cc”);

對的,就是這樣,這就是 javaScript 如何來模擬面向對象中的繼承的,還可以實現多重繼承。

function Class10()
{
this.showSub = function(a,b)
{
alert(a-b);
}
}

function Class11()
{
this.showAdd = function(a,b)
{
alert(a+b);
}
}


function Class2()
{
Class10.call(this);
Class11.call(this);
}

很簡單,使用兩個 call 就實現多重繼承了
當然,js的繼承還有其他方法,例如使用原型鏈,這個不屬於本文的範疇,只是在此說明call 的用法
說了call ,當然還有 apply,這兩個方法基本上是一個意思
區別在於 call 的第二個參數可以是任意類型,而apply的第二個參數必須是數組,也可以是arguments
還有 callee,caller,這個和call的 用法就不同了,放到下次講吧 ,呵呵。

caller
返回一個對函數的引用,該函數調用了當前函數。
functionName.caller
functionName 對象是所執行函數的名稱。
說明
對於函數來說,caller 屬性只有在函數執行時纔有定義。如果函數是由頂層調用的,那麼 caller 包含的就是 null 。如果在字符串上下文中使用 caller 屬性,那麼結果和 functionName.toString 一樣,也就是說,顯示的是函數的反編譯文本。
下面的例子說明了 caller 屬性的用法:

// caller demo {
function callerDemo() {
if (callerDemo.caller) {
var a= callerDemo.caller.toString();
alert(a);
}
else {
alert(
"this is a top function");
}
}
function handleCaller() {
callerDemo();
}

callee

返回正被執行的 Function 對象,也就是所指定的 Function 對象的正文。

[function.]arguments.callee

可選項 function 參數是當前正在執行的 Function 對象的名稱。

說明

callee 屬性的初始值就是正被執行的 Function 對象。

callee 屬性是 arguments 對象的一個成員,它表示對函數對象本身的引用,這有利於匿名
函數的遞歸或者保證函數的封裝性
,例如下邊示例的遞歸計算1n的自然數之和。而該屬性
僅當相關函數正在執行時纔可用。還有需要注意的是callee擁有length屬性,這個屬性有時候
用於驗證還是比較好的。arguments.length是實參長度,arguments.callee.length
形參長度,由此可以判斷調用時形參長度是否和實參長度一致。

示例
比較一般的遞歸函數:調用時:alert(sum(100));
其中函數內部包含了對sum自身的引用,函數名僅僅是一個變量名,在函數內部調用sum即相當於調用
一個全局變量,不能很好的體現出是調用自身,這時使用callee會是一個比較好的方法。

//callee可以打印其本身
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);
}
}
//遞歸計算
var sum = function(n){
if (n <= 0)
return 1;
else
return n +arguments.callee(n - 1)
}


var sum = function(n){
if (1==n) return 1;
else return n + sum (n-1);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章