javacscript apply and call

ForTechnology發表於2011-08-05
call方法:
語法:a.call(b,param1,param2.....paramN);
說明:a 方法,b方法,param1,param2.....paramN 為a方法的引數,引數可以有多個也可以沒有,多個引數用逗號隔開。
apply方法:
語法:a.apply(b,[param1,param2....paramN])
說明:a 方法,b方法,[param1,param2.....paramN] 為a方法的引數,引數可以有多個也可以沒有,必須以陣列的形式。
call和apply方法相同,只不過傳引數的方法不同,a、b兩個方法相當於繼承,a像父類,b像子類,b有a的所有方法。

    call && apply
    
    



<!--
 
function a(name,age){
    this.name=name;
    this.age=age;
    this.showName=function(){
        alert(this.name);   
    }
}
function b(dep){
    this.dep=dep;
}
var c = new b("English!!!")
//a.call(c,"black cat",19);
a.apply(c,["black cat",19]);
c.showName();
alert(c.dep);
// --&gt

看javascript的call 和apply的用法 收藏
本來是想在這裡寫寫call 和apply的用法,但是我剛在網上看到一篇討論,感覺比較講得徹底,拿過來吧 ,自己又懶了一把,
function foo(x) {
  this.x = x;
  var y = "Just a y";
}
function bar(foo) {
 return function() {
    var temp = {};
   foo.apply(temp, arguments);
    alert("In bar now");
    alert("temp.foo:" + temp.foo + "\n" +
      "temp.x:" + temp.x + "\n" +
      "temp.y:" + temp.y);//注意看這一行的執行結果
 }
}
var func = bar(foo);
func("In foo now");
試驗結果表明:apply以後,temp物件就繼承了foo類的公有變數了。也就是說,這一句 foo.apply(temp, arguments);實際上就是把foo()函式當成temp物件的建構函式來呼叫了。一旦構造完畢,temp物件就具有了成員this.x。
這樣,我有了兩種理解方案:
①按照傳統的物件導向的語言來理解:一般來說,建構函式是不能被外界(不包括派生類)訪問的。因此,這句話“呼叫apply時,是把foo函式變成temp物件的方法,然後呼叫”是正確的,而“可是temp.foo竟然沒有定義”則是理所當然的事情了。
②按照JavaScript語言自身的物件機制來理解:在JavaScript中,(構造 )函式就是國王、一等公民,它就是類就是它。物件則是(構造)函式的例項。因此,通過物件來訪問建構函式,顯然是行不通的。
其實,說構造未必準確(但我們可以利用建構函式來理解這個處理過程),我認為應該說成克隆,也就是說系統把foo類擁有的所有公有變數複製給了temp物件(這裡是指Object,Function,Array和包裝型物件“四類”物件)。
藍色的文字表明,如果temp不是一個物件型(指以上提到的四類物件)變數的話,克隆過程就不會發生,如下所示:
foo.apply(0, arguments);
foo.apply(null, arguments);
foo.apply(undefined, arguments);
foo.apply(true, arguments);
foo.apply("hello,world", arguments);
foo.apply({}, arguments);
那麼foo.apply()實際上就和普通的方法呼叫沒有什麼區別了,只是有了它,我們可以利用傳遞arguments引數的便利。
所以,apply(和call)的應用場合就浮現出來了:
①我們需要把一個類的公有變數複製給另一個物件。
②我們要快速而“智慧”的傳參,而不是手動去書寫arguments[0],arguments[1]...
問一個函式與函式之間傳引數的問題,我覺得我這種方法太麻煩,不知道大家還有沒有更好的方法.
如果按傳統的方式來,得這樣寫:
function  user( ) {
  test(arguments[0], arguments[1]);
}
function test(id,name) {
   alert(id +"-----------"+name);
}
user("dfdfd","kkkkk");
這樣寫的缺點很明顯,萬一引數一變,程式就掛了。
而利用apply,程式就變聰明多了:
function  user( ) {
  test.apply(0, arguments);
}
function test(id,name) {
   alert(id +"-----------"+name);
}
user("dfdfd","kkkkk");
apply(...)和call(...)確實很實用,比如實現一個類建立模式

<!--
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
};
var vehicle = Class.create();
vehicle.prototype = {
    initialize: function(type){
        this.type=type;
    },
    showSelf: function(){
        alert("this vehicle is "+ this.type);
    }
};
var moto=new vehicle("Moto");
moto.showSelf();
//--&gt


一個跨框架呼叫的例子
在View框架中有三個測試button,點選分別對應三種呼叫方式,第一種是通過最原始的obj.fn()來呼叫Controller框架中的fn函式,第二種是比較原始的eval拼裝arguments跨框架字串,第三種是改寫的apply方法應用~
/**
 * index.htm
 */




測試跨框架呼叫-apply()應用


 
 

<br>  UnSupport Frame. Structure! <br>


/**
 * view.htm
 */




:::View:::

<!--
// Cross Frames Function
var fFunc = function(){
 try{
  var iLen = arguments.length;
  if(iLen == 0) return;
  else{
   var sFuncStr = "top.frames['js_frame'].";
   sFuncStr += arguments[0] + "(";
   for(var i=1; i    sFuncStr += "'" + arguments[i] + "',";
   }
   sFuncStr = sFuncStr.substring(0, sFuncStr.length-1);
   sFuncStr += ");";
   eval(sFuncStr);
  }
 }
 catch(ex){
  window.alert("Error: " + ex.description);
 }
};
// Cross Frames Function Apply
var fGoto = function(){
 try{
  var sFuncStr = "top.frames['js_frame'].";
  var arr = [];
  for(var i=0; i   arr[i] = arguments[i];
  }
  arr = arr.slice(1);
  var func = eval(sFuncStr + arguments[0]);
  func.apply(window, arr);
 }
 catch(ex){
  window.alert("Error: " + ex.description);
 }
};
//--&gt









/**
 * controller.htm
 */




:::Controller:::

<!--
function fTest(sStr1, sStr2){
 window.confirm(sStr1);
 window.alert(sStr2);
}
//--&gt



:::JS Frame.:




提一點建議。。。利用apply的那一個函式可以優化如下:
// Cross Frames Function Apply
var fGoto = function(){
 try{ 
    var arr = [];
      for(var i=0; i       arr[i] = arguments[i];
      }
      arr = arr.slice(1);
   parent.frames['js_frame'][arguments[0]].apply(0, arr);
 }
 catch(ex){
  window.alert("Error: " + ex.description);
 }
};

 

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

相關文章