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則不會。
profile-image
Hi, 我是 Zeki。目前為一名前端工程師。我相信科技始終來自於人性,是用來幫助人們過上更有品質的生活的,但願也希望如此。