javascript函數apply和call

來源:互聯網
上載者:User

標籤:style   blog   http   io   ar   color   os   使用   sp   

 apply:方法能劫持另外一個對象的方法,繼承另外一個對象的屬性.

 Function.apply(obj,args)方法能接收兩個參數
obj:這個對象將代替Function類裡this對象
args:這個是數組,它將作為參數傳給Function(args-->arguments)

         call:和apply的意思一樣,只不過是參數列表不一樣.

 Function.call(obj,[param1[,param2[,…[,paramN]]]])
obj:這個對象將代替Function類裡this對象
params:這個是一個參數列表

1.        apply樣本:

[javascript] view plaincopy 
  1. <script type="text/javascript">  
  2.     /*定義一個人類*/  
  3.     function Person(name,age)  
  4.     {  
  5.         this.name=name;  
  6.         this.age=age;  
  7.     }  
  8.     /*定義一個學生類*/  
  9.     functionStudent(name,age,grade)  
  10.     {  
  11.         Person.apply(this,arguments);  
  12.         this.grade=grade;  
  13.     }  
  14.     //建立一個學生類  
  15.     var student=new Student("zhangsan",21,"一年級");  
  16.     //測試  
  17.     alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);  
  18.     //大家可以看到測試結果name:zhangsan age:21  grade:一年級  
  19.     //學生類裡面我沒有給name和age屬性賦值啊,為什麼又存在這兩個屬性的值呢,這個就是apply的神奇之處.  
  20. </script>  



分析: Person.apply(this,arguments);

this:在建立對象在這個時候代表的是student

arguments:是一個數組,也就是[“zhangsan”,”21”,”一年級”];

                   也就是通俗一點講就是:用student去執行Person這個類裡面的內容,在Person這個類裡面存在this.name等之類的語句,這樣就將屬性建立到了student對象裡面

 

2.        call樣本

在Studen函數裡面可以將apply中修改成如下:

Person.call(this,name,age);

這樣就ok了

3.        什麼情況下用apply,什麼情況下用call

在給對象參數的情況下,如果參數的形式是數組的時候,比如apply樣本裡面傳遞了參數arguments,這個參數是數群組類型,並且在調用Person的時候參數的列表是對應一致的(也就是Person和Student的參數列表前兩位是一致的) 就可以採用 apply , 如果我的Person的參數列表是這樣的(age,name),而Student的參數列表是(name,age,grade),這樣就可以用call來實現了,也就是直接指定參數列表對應值的位置(Person.call(this,age,name,grade));

4.        apply的一些其他巧妙用法

細心的人可能已經察覺到,在我調用apply方法的時候,第一個參數是對象(this), 第二個參數是一個數組集合, 在調用Person的時候,他需要的不是一個數組,但是為什麼他給我一個數組我仍然可以將數組解析為一個一個的參數,這個就是apply的一個巧妙的用處,可以將一個數組預設的轉換為一個參數列表([param1,param2,param3] 轉換為 param1,param2,param3) 這個如果讓我們用程式來實現將數組的每一個項,來裝換為參數的列表,可能都得費一會功夫,藉助apply的這點特性,所以就有了以下高效率的方法:

 

a)        Math.max 可以實現得到數組中最大的一項

因為Math.max 參數裡面不支援Math.max([param1,param2]) 也就是數組

但是它支援Math.max(param1,param2,param3…),所以可以根據剛才apply的那個特點來解決 var max=Math.max.apply(null,array),這樣輕易的可以得到一個數組中最大的一項(apply會將一個數組裝換為一個參數接一個參數的傳遞給方法)

         這塊在調用的時候第一個參數給了一個null,這個是因為沒有對象去調用這個方法,我只需要用這個方法幫我運算,得到返回的結果就行,.所以直接傳遞了一個null過去

b)        Math.min  可以實現得到數組中最小的一項

同樣和 max是一個思想 var min=Math.min.apply(null,array);

c)        Array.prototype.push 可以實現兩個數組合并

同樣push方法沒有提供push一個數組,但是它提供了push(param1,param,…paramN) 所以同樣也可以通過apply來裝換一下這個數組,即:

[javascript] view plaincopy 
  1. vararr1=new Array("1","2","3");  
  2.   
  3. vararr2=new Array("4","5","6");  
  4.   
  5. Array.prototype.push.apply(arr1,arr2);  

 

也可以這樣理解,arr1調用了push方法,參數是通過apply將數組裝換為參數列表的集合.

通常在什麼情況下,可以使用apply類似Math.min等之類的特殊用法:

一般在目標函數只需要n個參數列表,而不接收一個數組的形式([param1[,param2[,…[,paramN]]]]),可以通過apply的方式巧妙地解決這個問題!

1、每個函數都包含兩個非繼承而來的方法:apply()和call()。 
2、他們的用途相同,都是在特定的範圍中調用函數。 
3、接收參數方面不同,apply()接收兩個參數,一個是函數啟動並執行範圍(this),另一個是參數數組。
call()方法第一個參數與apply()方法相同,但傳遞給函數的參數必須列舉出來。 
  例1: 

複製代碼代碼如下:
window.firstName = "diz"; 
window.lastName = "song"; 
var myObject = { firstName: "my", lastName: "Object" }; 
function HelloName() { 
  console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!"); 

HelloName.call(window); //huo .call(this); 
HelloName.call(myObject); 


  運行結果為: 
Hello diz song glad to meet you! 
Hello my Object glad to meet you! 
  例2: 

複製代碼代碼如下:
function sum(num1, num2) { 
return num1 + num2; 

console.log(sum.call(window, 10, 10)); //20 
console.log(sum.apply(window,[10,20])); //30 


  分析:在例1中,我們發現apply()和call()的真正用武之地是能夠擴充函數賴以啟動並執行範圍,如果我們想用傳統的方法實現,請見下面的代碼: 

複製代碼代碼如下:
window.firstName = "diz"; 
window.lastName = "song"; 
var myObject = { firstName: "my", lastName: "Object" }; 
function HelloName() { 
console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!"); 

HelloName(); //Hello diz song glad to meet you! 
myObject.HelloName = HelloName; 
myObject.HelloName(); //Hello my Object glad to meet you! 


  見加紅的代碼,我們發現,要想讓HelloName()函數的範圍在對象myObject上,我們需要動態建立myObject的HelloName屬性,此屬性作為指標指向HelloName()函數,這樣,當我們調用myObject.HelloName()時,函數內部的this變數就指向myObjecct,也就可以調用該對象的內部其他公用屬性了。 
  通過分析例2,我們可以看到call()和apply()函數的真正運用之處,在實際項目中,還需要根據實際靈活加以處理! 
  一個小問題:再看一看函數中定義函數時,this變數的情況 

複製代碼代碼如下:
function temp1() { 
console.log(this); //Object {} 
function temp2() { 
console.log(this); //Window 

temp2(); 

var Obj = {}; 
temp1.call(Obj); //運行結果見上面綠色的注釋!!!! 


  執行結果與下面的相同: 

複製代碼代碼如下:
function temp1() { 
console.log(this); 
temp2(); 

function temp2() { 
console.log(this); 

var Obj = {}; 
temp1.call(Obj); 


4、bind()方法 
  支援此方法的瀏覽器有IE9+、Firefox4+、Safari5.1+、Opera12+、Chrome。它是屬於ECMAScript5的方法。直接看例子: 

複製代碼代碼如下:
window.color = "red"; 
var o = { color: "blue" }; 
function sayColor(){ 
alert(this.color); 

var OSayColor = sayColor.bind(o); 
OSayColor(); //blue 

5.        總結:

一開始我對apply 非常的不懂,最後多看了幾遍,自己多敲了幾遍代碼,才明白了中間的道理,所以,不管做什麼事情,只要自己肯動腦子,肯動手敲代碼,這樣一個技術就會掌握…   

還有比如第四部分得內容,巧妙的解決了實實在在存在的問題,這個肯定不是一個初學者能想到的解決方案(這個也不是我自己想的),沒有對編程有一定認識的不會想到這個的,還是一句話,多積累,多學習,提升自己的能力和對編程思想的理解能力才是最關鍵!

 

javascript函數apply和call

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.