js中 apply()和call() 還有bind的區別

一、call、apply的作用與應用
每個函數都包含兩個非繼承而來的方法:apply()和call()。這兩個方法的用途都是在特定的作用域中調用函數,實際上等於設置函數體內this對象的值。首先,apply()方法接收兩個參數:一個是在其中運行函數的作用域,另一個是參數數組。其中,第二個參數可以是Array的實例,也可以是arguments對象。例如:
 

function sum(num1, num2){
    return num1 + num2;
}
 
function callSum1(num1, num2){
    return sum.apply(this, arguments);        // 傳入arguments對象
}
 
function callSum2(num1, num2){
    return sum.apply(this, [num1, num2]);    // 傳入數組
}
 
alert(callSum1(10,10));   //20
alert(callSum2(10,10));   //20

在上面這個例子中,callSum1()在執行sum()函數時傳入了this作爲this值(因爲是在全局作用域中調用的,所以傳入的就是window對象)和arguments對象。而callSum2同樣也調用了sum()函數,但它傳入的則是this和一個參數數組。這兩個函數都會正常執行並返回正確的結果。

注意:在嚴格模式下,未指定環境對象而調用函數,則this值不會轉型爲window。除非明確把函數添加到某個對象或者調用apply()或call(),否則this值將是undefined。

call()方法與apply()方法的作用相同,它們的區別僅在於接收參數的方式不同。對於call()方法而言,第一個參數是this值沒有變化,變化的是其餘參數都直接傳遞給函數。換句話說,在使用call()方法時,傳遞給函數的參數必須逐個列舉出來,如下面的例子所示。
 

function sum(num1, num2){
    return num1 + num2;
}
 
function callSum(num1, num2){
    return sum.call(this, num1, num2);
}
 
alert(callSum(10,10));   //20

在使用call()方法的情況下,callSum()必須明確地傳入每一個參數。結果與使用apply()沒有什麼不同。至於是使用apply()還是call(),完全取決於你採取哪種給函數傳遞參數的方式最方便。如果你打算直接傳入arguments對象,或者包含函數中先接收到的也是一個數組,那麼使用apply()肯定更方便;否則,選擇call()可能更合適。(在不給函數傳遞參數的情況下,使用哪個方法都無所謂。)

事實上,傳遞參數並非apply()和call()真正的用武之地;它們真正強大的地方是能夠擴充函數賴以運行的作用域。下面來看一個例子。

window.color = "red";
var o = { color: "blue" };
 
function sayColor(){
    alert(this.color);
}
 
sayColor();                //red
 
sayColor.call(this);       //red
sayColor.call(window);     //red
sayColor.call(o);          //blue

sayColor()是作爲全局函數定義的,而且當在全局作用域中調用它時,它確實會顯示"red"——因爲對this.color的求值會轉換成對window.color的求值。而sayColor.call(this)和sayColor.call(window),則是兩種顯式地在全局作用域中調用函數的方式,結果當然都會顯示"red"。但是,當運行sayColor.call(o)時,函數的執行環境就不一樣了,因爲此時函數體內的this對象指向了o,於是結果顯示的是"blue"。

使用call()(或apply())來擴充作用域的最大好處,就是對象不需要與方法有任何耦合關係。再看如下代碼。
 

window.color = "red";
var o = { color: "blue" };
 
function sayColor(){
    alert(this.color);
}
 
sayColor();                //red
 
o.sayColor = sayColor;
o.sayColor();          //blue

我們是先將sayColor()函數放到了對象o中,然後再通過o來調用它的;而在上面的的例子中,就不需要現在這個多餘的步驟了

 

二、bind與call和apply的區別

bind()改過this後,不執行函數,會返回一個綁定新this的函數

ECMAScript 5還定義了一個方法:bind()。這個方法會創建一個函數的實例,其this值會被綁定到傳給bind()函數的值。例如:

window.color = "red";
var o = { color: "blue" };
 
function sayColor(){
    alert(this.color);
} 
var objectSayColor = sayColor.bind(o);
objectSayColor();    //blue

提到bind方法,估計大家還會想到call方法、apply方法;它們都是Function對象內建的方法,它們的第一個參數都是用來更改調用方法中this的指向。需要注意的是bind 是返回新的函數,以便稍後調用;apply 、call 則是立即調用原函數 。而今天我們主要講解bind方法的理解與使用。

bind方法是EcmaScript5新增的方法,該方法在mdn上是這麼介紹的:

  bind()方法創建一個新的函數(稱爲綁定函數), 當被調用時,將其this關鍵字設置爲提供的值,在調用新函數時,在任何提供之前提供一個給定的參數序列。

 語法:

fun.bind(thisArg[, arg1[, arg2[, ...]]])

  參數thisArg表示:當綁定函數被調用時,該參數會作爲this的指向。當使用new 操作符調用綁定函數時,該參數無效。

  參數arg1, arg2, ...表示:當綁定函數被調用時,這些參數將置於實參之前傳遞給被綁定的方法。

發佈了38 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章