在javascript中,函數也是對象,對象中能夠包含屬性和方法,而JavaScript的每一個函數都會擁有apply和call兩個非繼承而來的方法。這兩個均可以改變函數調用者(即this)的指向javascript
什麼意思?java
設想一下這樣一個場景,對象obj1中有一個方法fn(即函數)實現了一個功能,對象obj2也想擁有這樣的功能,但它又不想增長同樣的函數,由於這樣作的話會使得重複代碼過多,那麼obj2可不能夠在想用這個功能時問obj2借一下它的方法fn用一下呢?數組
答案是能夠的,就是使用apply和call方法,下面瞭解一下apply方法和call方法的使用和異同app
原始調用者:obj1函數
更改後的調用者:obj2this
要改變調用者的函數:fnspa
參數數組:param_arraycode
參數:param1,param2...對象
接收兩個參數:obj1.fn.call(obj2,param_array)blog
效果至關於:obj2.fn(...param_array)
注:...是ES6新增的操做符,至關於將param_array中的元素做爲fn的參數依次傳入
即obj2暫時擁有了fn這個方法(函數),而且param_array
例:
var obj1 = { //求和 add: function(...arr){ var sum = 0 for(var i = 0; i < arr.length; i++){ sum += arr[i] } return sum } } var obj2 = { //求平均值 average: function(...arr){ //暫時借用obj1的求和方法,至關於this.add(...arr) var sum = obj1.add.apply(this,arr) return sum/arr.length } } console.log(obj1.add(1,2,3,4)) //10 console.log(obj2.average(1,2,3,4)) //2.5
常見應用:求數組最大值
var arr = [1,5,3,4,2] console.log(Math.max.apply([],arr)) //5,這裏的第一個參數實際上能夠寫任意對象 console.log(Math.max.apply({},arr)) //5,沒影響 console.log(Math.max.apply(null,arr)) //5,傳null都行
補充,其餘求數組最大值的方式
先降序排序取最大值,破壞原數組順序
var arr = [1,5,3,4,2] arr.sort(function(a,b){ return b - a }) console.log(arr[0]) //5
ES6延展操做符,低版本不兼容
var arr = [1,5,3,4,2] console.log(Math.max(...arr)) //5
call ()方法與 apply ()方法的做用相同,它們的區別僅僅在千接收參數的方式不一樣。對於caII()方法而言,第—個參數是 this
值沒有變化,變化的是其他參數都直接傳遞給函數。換句話說,在使用 call()方法時, 傳遞給函數的參數必須逐個列舉出來
接收兩個(以上)參數:obj1.fn.call(obj2,param1,param2,...)
效果至關於:obj2.fn(param1,param2,...)
改造apply的例子:
將average方法的var sum = obj1.add.apply(this,arr)改爲var sum = obj1.add.call(this,...arr)便可
在ES6的環境下,因爲有延展操做符的加持,基本能夠用call來搞定,而在ES5及如下環境中,主要看參數形式,若是要傳的參數包含在一個數組中,推薦使用apply,不然使用call就能夠了