咱們都知道call
apply
bind
均可以改變函數調用的this
指向。那麼它們三者有什麼區別,何時該用哪一個呢?
咱們先直接經過代碼實例來了解,後面再借助專業文檔來解釋。javascript
// 有隻貓叫小黑,小黑會吃魚 const cat = { name: '小黑', eatFish(...args) { console.log('this指向=>', this); console.log('...args', args); console.log(this.name + '吃魚'); }, } // 有隻狗叫大毛,大毛會吃骨頭 const dog = { name: '大毛', eatBone(...args) { console.log('this指向=>', this); console.log('...args', args); console.log(this.name + '吃骨頭'); }, } console.log('=================== call ========================='); // 有一天大毛想吃魚了,但是它不知道怎麼吃。怎麼辦?小黑說我吃的時候餵你吃 cat.eatFish.call(dog, '汪汪汪', 'call') // 大毛爲了表示感謝,決定下次吃骨頭的時候也喂小黑吃 dog.eatBone.call(cat, '喵喵喵', 'call') console.log('=================== apply ========================='); cat.eatFish.apply(dog, ['汪汪汪', 'apply']) dog.eatBone.apply(cat, ['喵喵喵', 'apply']) console.log('=================== bind ========================='); // 有一天他們以爲每次吃的時候再喂太麻煩了。乾脆直接教對方怎麼吃 const test1 = cat.eatFish.bind(dog, '汪汪汪', 'bind') const test2 = dog.eatBone.bind(cat, '喵喵喵', 'bind') test1() test2()
call
跟apply
的用法幾乎同樣,惟一的不一樣就是傳遞的參數不一樣,call
只能一個參數一個參數的傳入。apply
則只支持傳入一個數組,哪怕是一個參數也要是數組形式。最終調用函數時候這個數組會拆成一個個參數分別傳入。
至於bind
方法,他是直接改變這個函數的this
指向而且返回一個新的函數,以後再次調用這個函數的時候this
都是指向bind
綁定的第一個參數。bind
傳餐方式跟call
方法一致。java
apply
函數傳參的特殊性,咱們又衍生出了一個黑魔法。// 若是一個數組咱們已知裏面全都是數字,想要知道最大的那個數,因爲Array沒有max方法,Math對象上有 // 咱們能夠根據apply傳遞參數的特性將這個數組當成參數傳入 // 最終Math.max函數調用的時候會將apply的數組裏面的參數一個一個傳入,剛好符合Math.max的參數傳遞方式 // 這樣變相的實現了數組的max方法。min方法也同理 const arr = [1,2,3,4,5,6] const max = Math.max.apply(null, arr) console.log(max) // 6
bind
函數也有一個小技巧// 若是你想將某個函數綁定新的`this`指向而且固定先傳入幾個變量能夠在綁定的時候就傳入,以後調用新函數傳入的參數都會排在以後 const obj = {} function test(...args) {console.log(args)} const newFn = test.bind(obj, '靜態參數1', '靜態參數2') newFn('動態參數3', '動態參數4')
call
語法fun.call(thisArg, arg1, arg2, ...)
thisArg
: 在fun函數運行時指定的this值。須要注意的是,指定的this值並不必定是該函數執行時真正的this值,若是這個函數處於非嚴格模式下,則指定爲null和undefined的this值會自動指向全局對象(瀏覽器中就是window對象),同時值爲原始值(數字,字符串,布爾值)的this會指向該原始值的自動包裝對象。arg1, arg2, ...
指定的參數列表apply
語法fun.apply(thisArg, [argsArray])
thisArg
在 fun 函數運行時指定的 this 值。須要注意的是,指定的 this 值並不必定是該函數執行時真正的 this 值,若是這個函數處於非嚴格模式下,則指定爲 null 或 undefined 時會自動指向全局對象(瀏覽器中就是window對象),同時值爲原始值(數字,字符串,布爾值)的 this 會指向該原始值的自動包裝對象。argsArray
一個數組或者類數組對象,其中的數組元素將做爲單獨的參數傳給 fun 函數。若是該參數的值爲null 或 undefined,則表示不須要傳入任何參數。從ECMAScript 5 開始可使用類數組對象。bind
語法fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg
當綁定函數被調用時,該參數會做爲原函數運行時的 this 指向。當使用new 操做符調用綁定函數時,該參數無效。arg1, arg2, ...
當綁定函數被調用時,這些參數將置於實參以前傳遞給被綁定的方法。this
指向的時候纔會用到call
`apply`bind
fn.call(thisObj, arg1, arg2 ...)
fn.apply(thisObj, [arg1, arg2 ...])
const newFn = fn.bind(thisObj); newFn(arg1, arg2...)