apply()方法定義
函數的apply()方法和call方法作用相同,區別在於接收的參數的方式不同。
apply()方法接收兩個參數,一個是對象,一個是參數數組。
apply()作用
1、用於延長函數的作用域
示例:
var color='red'; var o={color:'blue'}; function sayColor(){ console.log(this.color); } sayColor();//"red" sayColor.apply(o);//"blue"
這裡通過apply()方法把函數動態綁定到了對象o上了,這時this指向o對象,得到結果"blue"。
2、對象不需要與方法有任何耦合關系
下面舉個耦合的例子,看如何通過apply來解決這種耦合。
var color='red'; var o={color:'blue'}; function sayColor(){ console.log(this.color); } o.sayColor=sayColor; o.sayColor();//"blue"
這裡先將函數放到了對象o中,這裡對象和方法就緊耦合到一起了,方法的調用必須通過對象o。
沒有使用apply()和call()方法那樣靈活。
重構上面代碼,得到前例中的代碼。
var color='red'; var o={color:'blue'}; function sayColor(){ console.log(this.color); } sayColor();//"red" sayColor.apply(o);//"blue"
這裡對象並沒有綁定任何方法,只是在需要使用的時候,利用函數的apply或call方法來動態綁定。
對象和方法之間沒有耦合在一起。這裡還可以通過ES5提供的bind()方法來完成
3、實現可變參數函數傳參
下面一個計算任意數量數字平均值的函數
average(,,); average(); average(,,,,,,,,); average(,,,,,,,,,);
average函數是一個稱為可變參數或可變元函數(函數的元數是指其期望的參數個數)的例子。
當然這個函數也可以寫成一個接收數組的形式。
averageOfArray([,,]); averageOfArray([]); averageOfArray([,,,,,,,,]); averageOfArray([,,,,,,,,,]);
使用可變參數的函數更簡潔、優雅。可變參數函數具有便捷的語法,至少讓調用者預先明確地知道提供了多少個參數。
如果我有這樣一個數組
var scores=getAllScores();
如何使用average函數計算平均值呢?
1.可變參數函數版本。
這時就可以和apply()方法配合使用,這裡因為函數並沒用引用this變量,因此第一個參數我們傳入一個null。代碼如下:
var scores=getAllScores(); average.apply(null,scores);
2.直接參數為數組的形式
這裡可以直接傳入數組參數。
var scores=getAllScores(); averageOfArray(scores);
以上兩種形式,個人覺得都是可以,反而第二種更簡單。多知道一種方法,對於遇到別人寫的函數時,可以輕松應對,不需要重構代碼。這個好處反而更多。
4、實現可變參數方法的傳值
示例:buffer對象包含一個可變參數的append方法,該方法添加元素到函數內部的state數組中。
var buffer={ state:[], append:function(){ for(var i=,n=arguments.length;i<n;i++){ this.state.push(arguments[i]); } } };
這時append方法可以接受任意多個參數。
buffer.append('Hello,'); buffer.append('firtName',' ','lastName','!'); buffer.append('newLine');
形式如
buffer.append(arg1,arg2,arg3,...)
借助apply方法的this參數,我們可以指定一個可計算的數組調用append方法
buffer.append.apply(buffer,getInputStrings());
注意:這裡的buffer很重要,如果傳遞不同的對象,則append方法將嘗試修改該錯誤對象的state屬性。
提示
•使用apply方法指定一個可計算的參數數組來調用可變參數的函數
•使用apply方法的第一個參數給可變參數的方法提供一個接收者
附錄一
average函數
function average(){ var args=[].slice.call(arguments); var sum=args.reduce(function(prev,cur){ return prev+cur; }); return parseInt(sum/args.length,); }
averageOfArray函數
function averageOfArray(arr){ var sum=arr.reduce(function(prev,cur){ return prev+cur; }); return parseInt(sum/arr.length,); }
ES5 bind()方法
這個方法創建一個函數的實例,其this值會被綁定到傳給bind()函數的值。
例如
var color='red'; var o={color:'blue'}; function sayColor(){ console.log(this.color); } var oSayColor=sayColor.bind(o); oSayColor();//"blue"
兼容低版本,參考使用下面的版本 :
if (!Function.prototype.bind) { Function.prototype.bind = function(oThis) { if (typeof this !== 'function') { // closest thing possible to the ECMAScript // internal IsCallable function throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); } var aArgs = [].slice.call(arguments, ), fToBind = this, fNOP = function() {}, fBound = function() { return fToBind.apply(this instanceof fNOP? this: oThis, aArgs.concat(Array.prototype.slice.call(arguments))); }; if (this.prototype) { // Function.prototype doesn't have a prototype property fNOP.prototype = this.prototype; } fBound.prototype = new fNOP(); return fBound; }; }