iT邦幫忙

4

[筆記][JavaScript]使用call()、apply()、bind()設定函式中的「this」

HIHI,又來每週一篇惹,上禮拜的[筆記][JavaScript]認識JavaScript中的「this」大致上說明了JavaScript中的「this」,但是這個「this」是可以在呼叫function的時候用函式重新指定的,那些函式就是call()apply()bind(),也是這次要說的主題。

首先說明call(),他再呼叫function的時候可以使用多個參數,第一個為要為這個function指定的「this」,第二個開始會傳進去該function內當作引數,例如:

//首先宣告兩個物件
var objA = {
    Name:'A',
};

var objB = {
    Name:'B',
    writeName:function(age){
        console.log(this.Name + ' is ' + age + ' years old.');
    },
};

//呼叫objB的function並給他參數
objB.writeName(17); //會得到'B is 17 years old.'

//這時候我們利用call()來呼叫objB內的function並指定他的this為objA
objB.writeName.call(objA,19); //會得到'A is 19 years old.'

當我們用call()去呼叫objB.writeName()時,第一個參數放進objA,代表我將「this」指定給objA,所以他的this.Name會變成objA.Name,而第二個參數開始,會依序傳進funciton內當作引數,所以17會被objB.writeName()的age接收,最後印出「A is 19 years old.」

再來我們用apply()來呼叫objB.writeName()看看,apply()比較不同的是他只有兩個參數,第一個依然是為執行的function去指定「this」,而第二個參數必須提供陣列,陣列裡面每個位置的值依然會被依序傳入function內當作引數,例如:

objB.writeName.apply(objA,[20]); //會得到'A is 20 years old.'

當我們用apply()去呼叫objB.writeName()時,第一個參數一樣是指定「this」為objA,而第二個陣列中的所有項目會依序被傳入function內當作引數,所以陣列中第一個值20,會被傳進objB.writeName()的age裡面,最後印出最後印出「A is 20 years old.」。

最後來試看看bind(),給他的參數內容就和使用call()一樣,第一個參數指定「this」,第二個參數開始則會依序傳入被呼叫的function內當作引數,但是不一樣的是bind()他會創建一個新的函式,例如:

//把用bind創建的函式給變數func,這時候bind設定的「this」(objA)和參數(20)會同時被指定到func中
var func = objB.writeName.bind(objA,22);
func(); //執行後會得到'A is 22 years old.'

//也可以只設定「this」不設定其他參數值,等到呼叫的時候再給
var func1 = objB.writeName.bind(objA);
//執行func1,並給參數值
func1(24); //執行後會得到'A is 24 years old.'

當我們使用bind()的時候,他並不會執行呼叫的函式,而是會創建一個新的函式,而你可以在bind()的時候同時設定「this」或其他參數值給新函數。

所以用以下三種方式去改變objB.writeName()的「this」值所得到的結果都是相同的:

//call()
objB.writeName.call(objA,19);
//apply()
objB.writeName.apply(objA,[19]);
//bind()
var func = objB.writeName.bind(objA,19);
func();
//也可以這麼寫
var func1 = objB.writeName.bind(objA);
func1(19);

//都會回傳'A is 19 years old.'

以上就是這三個函式的使用方法,如果我有觀念錯誤或解釋不清楚的地方,還麻煩各位大大指點了,謝謝大家!


1 則留言

0
fysh711426
iT邦新手 1 級 ‧ 2018-03-11 23:00:52

原來除了 call 和 apply 還有 bind,
這三個函式在剛接觸 JS 時真的非常難理解。
/images/emoticon/emoticon13.gif

哈哈,我一開始就直接跳過
是之後才回來重看的/images/emoticon/emoticon01.gif

我要留言

立即登入留言