bind、call、apply的區別與用法?

咱們在看一些插件的時候,常常會用到這 3 個函數,那麼他們具體的用途是什麼呢?區別又是什麼呢?咱們先看看下面一段代碼:javascript

var name = '小白'
var obj = {
    name: '小明',
    getName: function () {
        console.log(this, this.name)
        return this.name
    }
}
var getName = obj.getName
obj.getName()
// obj, 小明
getName()
// window,小白

是否是很神奇,同一個函數,執行的結果不同,這裏涉及到一個this的指向問題。前端

函數中的this指向

js中一個普通函數this的指向與其自己無關,只與調用該函數的對象有關。根據這個規則,咱們回到上面的問題,obj.getName調用getName函數的對象是obj,因此this指向了obj對象,那麼獲得的obj.name爲小明;而getName()是直接調用的函數,其實是window.geName()window對象在調用函數,this則指向window對象。(use strict 嚴格模式下,全局 this 是 undefined,而不是window)。
關於this的指向這裏不作具體講解,畢竟這是個複雜的問題,後面再分狀況講解,畢竟這也是一個高頻面試題。java

bind、call、apply 的做用

這 3 個函數的做用是,改變一個函數在執行時this的指向。咱們來改造上面的代碼。面試

var name = '小白';
var obj = {
    name: '小明',
    getName: function () {
        console.log(this, this.name)
        return this.name
    }
};

var obj1 = {name: '小花'}

var getName = obj.getName;
getName();
// window,小白
obj.getName();
// obj, 小明
getName.apply(obj);
// obj,小明
getName.call(obj1);
// obj1,小花
getName.bind(obj)();
// obj,小明

能夠看到,當咱們改用apply去調用函數時,無論其所在的做用域,咱們的this指向bind,apply,call函數接受的第一個參數。數組

相同點與不一樣點

相同點:三個函數都是爲了改變被調用函數的this指向,都指向接受的第一個參數。
不一樣點:app

  1. applycall都是直接調用函數,而bind則是先將函數暫存起來,須要再單獨調用一次。
  2. applycall第一個參數同樣,都是要綁定給 this 的值,若是這個值爲null或者undefined,則爲window對象。他們的區別在第二個參數上:當函數須要傳遞多個變量時, apply能夠接受一個數組做爲參數輸入, call 則是接受一系列的單獨變量。當參數個數已知的時候能夠用call,而當參數個數不肯定的時候能夠用apply
  3. bindcall很類似,第一個參數是this的指向,從第二個參數開始是接收的參數列表。區別在於bind方法返回值是函數以及bind接收的參數列表的使用。bind 方法不會當即執行,而是返回一個改變了上下文 this後的函數。而不會影響原函數中的this指向。

最後咱們再看一個完整的實例來表現這個三個函數的用途和區別:函數

function sub(a, b) {
        const sub = a + b
        console.log(sub)
        return sub
    }
    sub.call(null, 1, 2)
    sub.apply(null, [1, 2])
    sub.bind(null, 1, 2)()

能夠看到,callapply參數不同,而bind參數和call同樣,但還須要單獨調用一下函數。學習

應用場景

求數組中的最大和最小值
var arr = [0,8,3,46]
var max = Math.max.apply(null,arr);//46
var min = Math.min.apply(null,arr);//0
// 等價於
var max = window.Math.max(...arr);
var min = window.Math.min(...arr);
這裏利用 apply的第二個參數是接受一個數組,而在調用函數的時候會自動展開這個數組,而 max和min方法接受參數的形式是(1,2,3,4)。
將 arguments 等類數組轉換爲數組
var trueArr = Array.prototype.slice.call(arguments,0,arguments.length)
判斷變量類型
function isArray(obj){
    return Object.prototype.toString.call(obj) == '[object Array]';
}
isArray([]) // true
isArray('dot') // false
使用 log 代替 console.log
function log(){
  console.log.apply(console, arguments);
}

以上用途參考:call、apply 和 bind 方法的用法以及區別this

總結

callapplybind都是爲了改變當前要執行函數this指向,由第一個參數決定,爲null或者undefined時則爲window對象。callapply的參數有區別。而bind不是立刻執行函數,而是返回該函數和保留該函數的執行上下文。spa

學習如逆水行舟,不進則退,前端技術飛速發展,若是天天不堅持學習,就會跟不上,我會陪着你們,天天堅持推送博文,跟你們一同進步,但願你們能關注我,第一時間收到最新文章。

我的公衆號:長按保存關注

相關文章
相關標籤/搜索