在 javascript 中,call、apply和bind 都是爲了改變某個函數運行時的上下文(context)而存在的,換句話說,就是爲了改變函數體內部 this 的指向。
舉個例子先:javascript
let person = { name:'Lucy', say:function () { console.log(this.name) } } person.say() // Lucy
若是咱們有個person一、person二、person3,想要調用person的say方法,又不想從新定義say方法,能夠這樣:java
let person1 = { name:'Lily' } let person2 = { name:'Jack' } let person3 = { name:'Cici' } person.say.call(person1) // Lily person.say.apply(person2) // Jack person.say.bind(person3)() // Cici
因此,能夠看出 call、apply、bind 是爲了動態改變 this 而出現的,當一個 object 沒有某個方法(本栗子中person一、person二、person3沒有say方法),可是其餘的有,咱們能夠藉助call或apply或bind用其它對象的方法來操做。數組
對於call和apply而言,他們的做用是同樣的,區別在於接收的參數不同,call 須要把參數按順序傳遞進去,而 apply 則是把參數放在數組裏,例如:app
let person = { name:'Lucy', say:function (a,b) { console.log(a+this.name+b) } } person.say('<','>') // <Lucy> let person1 = { name:'Lily' } let person2 = { name:'Jack' } let person3 = { name:'Cici' } person.say.call(person1,'<','>') // <Lily> person.say.apply(person2,['<','>']) // <Jack> person.say.bind(person3,'<','>')() // <Cici>
對於bind而言,咱們能夠看到用bind調用函數,後面還須要一個括號。MDN的解釋是:bind()方法會建立一個新函數,稱爲綁定函數,當調用這個綁定函數時,綁定函數會以建立它時傳入 bind()方法的第一個參數做爲 this,傳入 bind() 方法的第二個以及之後的參數加上綁定函數運行時自己的參數按照順序做爲原函數的參數來調用原函數。也就是說,區別是,當你但願改變上下文環境以後並不是當即執行,而是回調執行的時候,使用 bind() 方法。而 apply/call 則會當即執行函數。dom
一、數組之間追加函數
let arr1 = [1,2,3] let arr2 = [4,5,6] Array.prototype.push.apply(arr1,arr2) //[1,2,3,4,5,6]
二、獲取數組中的最大值和最小值this
let numbers = [-1,10,20,101] let max = Math.max.call(Math,...numbers) // 101 let min = Math.min.apply(Math,numbers) // -1
number 自己沒有 max 方法,可是 Math 有,咱們就能夠藉助 call 或者 apply 使用其方法。
三、驗證是不是數組(前提是toString()方法沒有被重寫過)prototype
function isArray(obj){ return Object.prototype.toString.call(obj) === '[object Array]' }
四、類(僞)數組使用數組方法code
let domList = Array.prototype.slice.call(document.getElementsByTagName('*'))
Javascript中存在一種名爲僞數組的對象結構。比較特別的是 arguments 對象,還有像調用 getElementsByTagName , document.childNodes 之類的,它們返回NodeList對象都屬於僞數組。不能應用 Array下的 push , pop 等方法。可是咱們能經過 Array.prototype.slice.call 轉換爲真正的數組的帶有 length 屬性的對象,這樣 domList 就能夠應用 Array 下的全部方法了。對象
Function.prototype._bind = function(){ var self = this //原函數 var context = Array.prototype.shift.call(arguments) //this上下文 var args = Array.prototype.slice.call(arguments) //參數 return function(){ self.apply(context, args.concat([].slice.call(arguments))) } }