@TOCjavascript
在咱們平常開發過程當中call、bind、apply無疑是咱們用的比較多的語法,今天在開發中看到有同事傻傻分不清call和bind的區別,故在解釋一通以後,寫下此文;java
從MDN 文檔 call咱們能夠了解到: call() 方法使用一個指定的 this 值和單獨給出的一個或多個參數來調用一個函數。git
fun
函數運行時指定的 this
值*。*須要注意的是,指定的 this
值並不必定是該函數執行時真正的 this
值,若是這個函數在非嚴格模式
下運行,則指定爲 null
和 undefined
的 this
值會自動指向全局對象(瀏覽器中就是 window 對象),同時值爲原始值(數字,字符串,布爾值)的 this
會指向該原始值的自動包裝對象。(ps:嚴格模式下 咱們對函數的的調用必須嚴格的寫出被調用的函數的對象);先舉個例子:github
// main.js
const foo={
name:'foo',
getFoo(...args){
console.log('this===',this,'this.name==',this.name)
console.log('-----------------------------------')
console.log('...args=====',...args)
}
}
const bar={
name:'bar',
getBar(...args){
console.log('this===',this,'this.name==',this.name)
console.log('-----------------------------------')
console.log('...args=====',...args)
}
}
foo.getFoo() //this=== {name: "foo", getFoo: ƒ} this.name== foo ----------------------------------- ...args=====
bar.getBar() //this=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args=====
複製代碼
假如咱們想在getFoo去借bar裏面的東西用用,該怎麼辦呢? 也許有同窗想到的是這樣:數組
foo.getFoo(bar.name) // this=== {name: "foo", getFoo: ƒ} this.name== foo ----------------------------------- ...args===== bar
複製代碼
毫無疑問,這是沒問題的,但此時只是正常的傳參,可否乾脆點把this.name也改爲bar呢;根據call的定義:瀏覽器
foo.getFoo.call(bar,'測試傳參','測試call') //his=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 測試傳參 測試call
//使用call後,咱們能夠看到foo.getFoo的this此時指向了bar對象,此時的name拿到的bar的對象的name;
複製代碼
從MDN 文檔 apply咱們能夠了解到: apply()
方法調用一個具備給定this
值的函數,以及做爲一個數組(或相似數組對象)提供的參數。app
func.apply(thisArg, [argsArray])ide
thisArg:可選的。在 func
函數運行時使用的 this
值。請注意,this
可能不是該方法看到的實際值:若是這個函數處於非嚴格模式下,則指定爲 null
或 undefined
時會自動替換爲指向全局對象,原始值會被包裝。函數
argsArray:可選的。一個數組或者類數組對象,其中的數組元素將做爲單獨的參數傳給 func
函數。若是該參數的值爲 null
或 undefined
,則表示不須要傳入任何參數。從ECMAScript 5 開始可使用類數組對象。 瀏覽器兼容性 請參閱本文底部內容。測試
繼續使用剛纔的foo和bar
foo.getFoo.apply(bar,['測試傳參','測試apply']) //his=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 測試傳參 測試apply
複製代碼
總結 call方法和apply方法二者極度類似,區別就是call()方法接受的是參數列表,而apply()方法接受的是一個參數數組。
從MDN 文檔 bind咱們能夠了解到:
bind()方法建立一個新的函數,在調用時設置this關鍵字爲提供的值。並在調用新函數時,將給定參數列表做爲原函數的參數序列的前若干項。
function.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg 調用綁定函數時做爲this
參數傳遞給目標函數的值。 若是使用new
運算符構造綁定函數,則忽略該值。當使用bind
在setTimeout
中建立一個函數(做爲回調提供)時,做爲thisArg
傳遞的任何原始值都將轉換爲object
。若是bind
函數的參數列表爲空,執行做用域的this
將被視爲新函數的thisArg
。
arg1, arg2, ... 當目標函數被調用時,預先添加到綁定函數的參數列表中的參數。
emmmm...繼續最最上面的那個foo和bar
foo.getFoo.bind(bar,'測試傳參','測試bind') // 此時是無輸出,由於bind()方法建立一個新的函數,當前函數並無執行
複製代碼
修改以下:
const foobindbar = foo.getFoo.bind(bar,'測試傳參','測試bind');
console.log(foobindbar)
// ƒ getFoo(...args){
// console.log('this===',this,'this.name==',this.name)
// console.log('-----------------------------------')
// console.log('...args=====',...args)
// }
foobindbar() //this=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 測試傳參 測試apply
複製代碼
call方法和apply方法二者極度類似,區別就是call()方法接受的是參數列表,而apply()方法接受的是一個參數數組。用apply時,即便傳入的參數只有一個,也必須定義爲數組才行;
call與apply改變this的指向時,會直接觸發函數;而bind會建立一個新的函數,在調用時設置this關鍵字爲提供的值,使用bind時,會優先使用bind綁定的幾個值; 以下:
foo.getFoo.bind(bar,'測試傳參','測試bind')
const foobindbar = foo.getFoo.bind(bar,'測試傳參','測試bind');
console.log(foobindbar)
// ƒ getFoo(...args){
// console.log('this===',this,'this.name==',this.name)
// console.log('-----------------------------------')
// console.log('...args=====',...args)
// }
foobindbar('參數1', '參數2') //this=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 測試傳參 測試apply 參數1 參數2
// ...args===== 測試傳參 測試apply 參數1 參數2
複製代碼
文章所示demo請轉王一諾/github