JavaScript 全攻略:克服 JS 的奇怪部分 - 物件與函數 - call()、apply()、bind()

介紹JavaScript中function原生的三個方法(method)與用法

後面會講function borrowing 與 function currying

在JavaScript中,function會有三個原生的方法,分別是call()、apply()、bind(),而這三個方法的目的都是一樣的,為了改變this的指向。

記得在最前面的章節有提到:參考 JavaScript 全攻略:克服 JS 的奇怪部分 - 執行環境與詞彙環境(1)

在Global Execution context 中會產生一個全域物件,叫做window,在全域環境中,他和this是相同的,this會指向window這個物件,你可以按下F12,在Console中輸入this,看看會印出什麼?

就是window

現在可以來看看程式碼

var person = {
    firstname: 'John',
    lastname: 'Doe',
    getFullName: function() {
        
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;
        
    }
}

我們可以知道,在getFullName中的this會指向person

接著再寫一段程式碼,我們想使用getFullName

var logName = function(lang1, lang2) {

    console.log('Logged: ' + this.getFullName());
    console.log('Arguments: ' + lang1 + ' ' + lang2);
    console.log('-----------');
    
}

logName('Scott','Go');

這邊執行會報錯

主要是在這個function裡面,this是指向window,這樣我們要怎麼樣才能使用Person物件中的getFullName與property呢?

bind()

bind可以改變this的指向,在這邊我們是要使用Person物件中的getFullName,所以我們會這樣寫:

logName.bind(person)('Scott','Go');

注意:因為bind是原生function中的method,故我們的寫法會是functionName.bind(欲指向的物件),而我們為了要執行logName這個function,所以最後要加上()來執行,最後會跑出結果。

call()

call與bind一樣,它們唯一的差別在於call是改變this之後,會順便執行呼叫call的function

logName.call(person, 'Scott', 'Go');

 

apply()

同call也會直接執行,不同點在於定二個參數是吃array

logName.apply(person, ['Scott', 'Go']);

所以這三個寫法互為等價:

logName.bind(person,'Scott','Go')();
logName.call(person, 'Scott', 'Go');
logName.apply(person, ['Scott', 'Go']);

之後,講師做了一些延伸:提到兩個專有名詞function borrowing 與 function currying

function borrowing:

如下程式碼:

var person = {
    firstname: 'John',
    lastname: 'Doe',
    getFullName: function() {
        
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;
        
    }
}

var person2 = {
    firstname: 'Jane',
    lastname: 'Doe'
}

//function borrowing
console.log(person.getFullName.apply(person2));

person2想把自己的property丟到person中的getFullName去使用,就可以這樣寫,印出結果如下。

function currying

作者寫了一個multiply的function,但想讓a的值變成2,只留下參數b傳入,就可以這樣寫:

// function currying
function multiply(a, b) {
    return a*b;   
}

var multipleByTwo = multiply.bind(this, 2);
console.log(multipleByTwo(4));

這樣寫的好處是,每次用multipleByTwo這個function的時候,就不用重新設定第一個參數(因為已經設定好a=2)

其實function就很像這個樣子

function multiply(b) {
    return 2*b;   
}

這裡講到function currying的概念,有興趣可以看看這篇:連結

Curry 的概念很簡單:你可以只透過部分的參數呼叫一個 function,它會回傳一個 function 去處理剩下的參數。

 

 

參考資料

https://www.udemy.com/javascriptjs/learn/v4/overview