- 三種方法都可改變函數
this
關鍵字的指向。apply()
接受一參數數組,返回函數執行的結果。call()
接受一組參數,返回函數執行的結果。bind()
接受一組參數,返回函數體。需在bind()
後加小括號才能執行函數。- 箭頭函數的
this
綁定後不管使用apply()
、call()
仍是bind()
都不可修改。
this
關鍵字
- JavaScript中的函數存在
定義上下文
和運行上下文
,經過call()
、apply()
和bind()
能夠改變this
的指向。this
總指向運行上下文。
定義上下文更準確的名稱應該叫詞法做用域,它指函數的定義部分所造成的做用域。javascript
function fun1 () {
// 函數fun1的詞法做用域
// 函數定義
// ....
}
複製代碼
函數在調用時會產生一個調用記錄,其中包含函數在哪裏被調用、傳入函數的參數等信息。該記錄也被稱爲運行上下文。一個函數的this
總指向函數的運行上下文。當fun1
在fun2
中調用時,fun1
的this
指向fun2
的定義上下文(詞法做用域)。java
function fun2 () {
// fun1的this指向該做用域
fun1();
// 函數定義
// ...
}
複製代碼
this
的指向this
是運行上下文的一個屬性,所以常說this
指向函數的運行上下文。
this
是在函數調用時被綁定的,與函數的聲明位置(即詞法做用域)沒有任何關係。數組
call()
和apply()
call()
call()
方法的第一個參數爲要指定的this
對象,第二個參數及之後爲函數運行所需的參數列表。app
let obj = {
a: 1
}
function fun1 (num1, num2) {
console.log(this); // obj {a: 1}
console.log(num1 + num2); // 3
console.log(this.a); // 1
}
fun1.call(obj, 1, 2);
複製代碼
上述代碼展現了call()
的兩種能力。一方面它改變了fun1
調用時的this
關鍵字,讓其指向obj,並經過this
關鍵字來訪問obj
中的屬性。另外一方面它將本身接受到的參數傳入fun1
。函數
apply()
call()
和apply()
本質上並沒有太大差異,惟一的區別在於call()
接受的是參數列表,而apply()
接受的是一個參數數組。ui
// ··· 同上
fun1.apply(obk, [1, 2]); // 效果和fun1.call(obj, 1, 2)相同
複製代碼
bind()
bind()
建立一個新的函數, 當這個新函數被調用時this
鍵值爲其提供的值,其參數列表前幾項值爲建立時指定的參數序列。 ----- MDNthis
bind()
的使用方法和call()
十分相似,它的第一個參數是須要綁定的this
對象,以後的參數爲函數運行所需的參數列表。下面讓咱們來試驗一下。spa
let obj = {
a: 1
}
function fun1 (num1, num2) {
console.log(this);
console.log(num1 + num2);
console.log(this.a);
}
fun1.bind(obj, 1, 2); // fun1 { ··· }
複製代碼
不一樣於apply()
和call()
,bind()
返回的並非fun1
執行完畢的返回值,而是更改了this
並初始化參數以後的fun1
的函數定義。所以,要執行fun1
,需在bind()
後面再加一對括號:code
fun1.bind(obj, 1, 2)(); // 改變this並傳入參數後執行fun1
複製代碼
apply()
、call()
和bind()
的比較this
關鍵字的指向。apply()
接受一參數數組,返回函數執行的結果。call()
接受一組參數,返回函數執行的結果。bind()
接受一組參數,返回函數體。需在bind()
後加小括號才能執行函數。this
綁定ES6中新加入了箭頭函數,它的綁定徹底繼承自調用它的做用域。綁定後不管使用apply()
、call()
仍是bind()
都不可修改。對象