2021年4月10日 星期六

bind和call、apply的差別

//bind有兩種方式,第一種是綁定物件,第二種是綁定函中的參數,綁定完會回傳綁定後的函式。

//bind第一種,綁定物件。

var msg = 'Window(global) msg';


//在還沒綁定物件時,此時printLog這個函式裡的this指向的是全域的window(nodejs裡是global)

function printLog(msg) { console.log(this.msg); } var scope = { msg: 'Scope msg' }

var scopePrintLog = printLog.bind(scope); //綁定scope物件後,此時printLog這個函裡的this指向的是scope這個物件,但bind不會立即執行函式,而是把綁定物件後的函回傳存入scopePrintLog變數裡。


printLog(); //result: Window(global) msg scopePrintLog(); //result: Scope msg


//bind第二種,綁定函中的參數。

function sum(a,b) { return a + (b||0) }  

var bindPlusOne = sum.bind(this, 1); //綁定sum這個函數的參數,依照你想綁定幾個參數,這裡只輸入一個數字1,所以只有綁定sum函數中的參數a,此時的sum函數變成像是這樣:

/*function sum(b) { return 1 + (b||0) }*/

//一樣bind不會立即執行函式,而是把綁定參數後的函數回傳存入bindPlusOne變數裡。


sum(5,5); //result: 10 bindPlusOne(); //result: 1 bindPlusOne(6); //result: 7





//call、apply和bind很類似,但這兩個方法與bind的最大差別在於,call和apply在綁定完物件或參數後會立即執行函式,而不是回傳綁定後的函式。
//同上例子,只是把bind換成call和apply:

function sum(a,b) { return a + (b||0) }  

var bindPlusOne = sum.call(this, 1); //綁定sum這個函數的參數,依照你想綁定幾個參數,這裡只輸入一個數字1,所以只有綁定sum函數中的參數a,此時的sum函數變成像是這樣:

/*(function sum(b) { return 1 + (b||0) }())*/

//跟bind不一樣的地方是call綁定完會立即執行函式,然後再執行的函式裡如果有retrun,才會回傳運算的結果,否則不會回傳。


bindPlusOne(); //result: Uncaught TypeError: bindPlusOne is not a function bindPlusOne(6); //result: Uncaught TypeError: bindPlusOne is not a function bindPlusOne; //result: 1
//所以你會發現在執行call的同時他不僅綁定了函數裡面的參數,綁定完還立即執行了函式。

//apply與call類似,只是傳入的參數的形式不同。
//同上例子,只是把call換成apply:

function sum(a,b) { return a + (b||0) } var bindPlusOne = sum.apply(this, [1]);

//這裡apply和call的差別只在於,呼叫call函式時call在this後面的參數是逐項輸入參數,而apply是在this後面的參數只需要輸入一個陣列的參數。所以apply會自動解構陣列為個別值,而call則不會。

沒有留言:

張貼留言