ECMAScript中的函數是對象,所以函數也有屬性和方法。每一個函數都包含兩個屬性:length和prototype,且每一個函數包含兩個非繼承而來的方法apply()和call()。這兩個方法的用途都是在特定的做用域中調用函數,實際上等於設置函數體內thiis對象的值。javascript
apply()方法接受兩個參數:一個是在其中運行函數的做用域,另外一個是參數數組。其中,第二個參數能夠是Array的實例,也能夠是arguments對象。 java
定義:應用某一對象的一個方法,用另外一個對象替換當前對象。即apply()方法能劫持另一個對象的方法,繼承另一個對象的屬性. 數組
語法:Function.apply(obj,args)方法能接收兩個參數
說明:obj:這個對象將代替Function類裏this對象 args:這個是數組,它將做爲參數傳給Function(args-->arguments)瀏覽器
若是 args 不是一個有效的數組或者不是 arguments 對象,那麼將致使一個 TypeError。
若是沒有提供 args 和 obj 任何一個參數,那麼 Global 對象將被用做 obj, 而且沒法被傳遞任何參數。app
apply()和call()方法的做用相同,它們的區別僅在於接收參數的方式不一樣。對於call()方法而言,第一個參數是this值沒有變化,變卦的是其他參數都直接傳遞給函數。換句話說,在使用call()方法時,傳遞給函數的參數必須逐個列舉出來。函數
語法:Function.call(obj,[param1[,param2[,…[,paramN]]]])
定義:調用一個對象的一個方法,以另外一個對象替換當前對象。
說明: obj:這個對象將代替Function類裏this對象 params:這個是一個參數列表 測試
call 方法能夠用來代替另外一個對象調用一個方法。call 方法可將一個函數的對象上下文從初始的上下文改變爲由 thisObj 指定的新對象。
若是沒有提供 obj 參數,那麼 Global 對象被用做 obj。this
舉例:spa
1 <script type="text/javascript"> 2 /*定義一我的類*/ 3 function Person(name,age) { 4 this.name=name; this.age=age; 5 } 6 /*定義一個學生類*/ 7 function Student(name,age,grade) { 8 Person.apply(this,arguments); this.grade=grade; 9 } 10 //建立一個學生類 11 var student=new Student("qian",21,"一年級"); 12 //測試 13 alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade); 14 //你們能夠看到測試結果name:qian age:21 grade:一年級 15 //學生類裏面我沒有給name和age屬性賦值啊,爲何又存在這兩個屬性的值呢,這個就是apply的神奇之處. 16 </script>
分析: Person.apply(this,arguments); .net
this:在建立對象在這個時候表明的是student
arguments:是一個數組,也就是[「qian」,」21」,」一年級」];
也就是通俗一點講就是:用student去執行Person這個類裏面的內容,在Person這個類裏面存在this.name等之類的語句,這樣就將屬性建立到了student對象裏面
apply和call的區別在哪裏(僅僅只是接受參數的方式不一樣)
什麼狀況下用apply,什麼狀況下用call
在給對象參數的狀況下,若是參數的形式是數組的時候,好比apply示例裏面傳遞了參數arguments,這個參數是數組類型,而且在調用Person的時候參數的列表是對應一致的(也就是Person和Student的參數列表前兩位是一致的) 就能夠採用 apply ;若是個人Person的參數列表是這樣的(age,name),而Student的參數列表是(name,age,grade),這樣就能夠用call來實現了,也就是直接指定參數列表對應值的位置(Person.call(this,age,name,grade))。 在不給函數傳遞參數的狀況下,使用哪一個方法都無所謂。
apply的其餘巧妙用法(通常在什麼狀況下可使用apply)
調用apply方法的時候,第一個參數是對象(this), 第二個參數是一個數組集合, 這裏就說明apply的一個巧妙用法,能夠將一個數組默認的轉換爲一個參數列表([param1,param2,param3] 轉換爲 param1,param2,param3), 這個若是讓咱們用程序來實現將數組的每個項,來裝換爲參數的列表,可能都得費一會功夫,藉助apply的這點特性,因此就有了如下高效率的方法。
(1)Math.max 實現獲得數組中最大的一項
由於Math.max 參數裏面不支持Math.max([param1,param2]) 也就是數組 ,可是它支持Math.max(param1,param2,param3…),因此
能夠根據剛纔apply的那個特色來解決 var max=Math.max.apply(null,array),這樣輕易的能夠獲得一個數組中最大的一項 (apply會將一個數組裝換爲一個參數接一個參數的傳遞給方法)
這塊在調用的時候第一個參數給了一個null,這個是由於沒有對象去調用這個方法,我只須要用這個方法幫我運算,獲得返回的結果就行,.因此直接傳遞了一個null。
var arr = new Array(1,2,3,4,5); var max = Math.max.apply(null,arr); //5
(2)Array.prototype.push 能夠實現兩個數組合並
一樣push方法沒有提供push一個數組,可是它提供了push(param1,param,…paramN);
var arr1=new Array("1","2","3"); var arr2=new Array("4","5","6");
若是咱們要把 arr2展開,而後一個一個追加到arr1中去,最後讓arr1=[「1」,「2」,「3」,「4」,「5」,「6」]
arr1.push(arr2)顯然是不行的,由於這樣作會獲得[「1」,「2」,「3」,[「4」,「5」,「6」]]
咱們只能用一個循環去一個一個的push(固然也能夠用arr1.concat(arr2),可是concat方法並不改變arr1自己)
var arrLen=arr2.length; for(var i=0;i<arrLen;i++){ arr1.push(arr2[i]); }
因此一樣也能夠經過apply來轉換一下這個數組,即:
var arr1=new Array("1","2","3"); var arr2=new Array("4","5","6"); Array.prototype.push.apply(arr1,arr2);
也能夠這樣理解,arr1調用了push方法,參數是經過apply將數組裝換爲參數列表的集合.。
ECMAScript5還定義了一個方法:bind()。這個方法會建立一個函數的實例,其this值會被綁定到傳給bind()函數的值。
1 <script type="text/javascript"> 2 3 window.color = "red"; 4 var o = { color: "blue" }; 5 6 function sayColor(){ 7 alert(this.color); 8 } 9 var objectSayColor = sayColor.bind(o); 10 objectSayColor(); //blue 11 12 13 </script>
在這裏,sayColor()調用bing()並傳入對象o,建立了objectSayColor()函數。objectSayColor()函數的this值等於o,所以即便是在全局做用域中調用這個函數,也會看到「blue」。
bind()主要是爲了改變函數內部的this指向,這個是在ECMA5之後加入的,因此IE8一下的瀏覽器不支持。
bind()方法會建立一個新函數,稱爲綁定函數.當調用這個綁定函數時,綁定函數會以建立它時傳入bind方法的第一個參數做爲this,傳入bind方法的第二個以及之後的參數加上綁定函數運行時自己的參數按照順序做爲原函數的參數來調用原函數.
參考:Js apply()使用詳解 js高程P116-118