js裏function的apply vs. bind vs. call

js裏除了直接調用obj.func()以外,還提供了另外3種調用方式:apply、bind、call,都在function的原型裏。這3種方法的異同在stackoverflow的這個答案裏說的最清楚,下面只是本身的理解。python

1. 異同

這3種方式的相同點是:改變了func調用的上下文,連接到新的對象上。這使得任何函數均可以被其餘對象調用,即便這個對象沒有定義該函數。數組

區別是:調用的方式不一樣。app

  1. call: 最簡單,當即調用,按順序傳參
  2. apply:當即調用,按數組傳參
  3. bind: 延遲調用(返回一個新的func),按順序傳參

2. 例子

上代碼:函數

var person = {
    name: "Alex",
    code: function(lang1, lang2, lang3, lang4){
        //在這裏斷點,觀察arguments和lang1-4的區別
        console.log(this.name + " code in " + arguments.toString());
    }
};

var machine = {
    name: "alphago"
};

//普通的調用方式
person.code("C#");

//call是按順序傳參
person.code.call(machine, "python", "perl");

//apply是按數組傳參,若是不能轉成數組,拋TypeError
person.code.apply(machine, ["C", "C++", "lisp"]);
//Uncaught TypeError: CreateListFromArrayLike called on non-object
//person.code.apply(machine, "C", "C++", "lisp");
//不報錯,但轉出的數組爲空
//person.code.apply(machine, {lang1:"C", lang2:"C++", lang3:"lisp"});

var func = person.code.bind(machine);
func("python", "perl");
//按順序傳參,相似call
//func(["C", "C++", "lisp"]);

var func1 = person.code.bind(machine, "python", "perl");
func1("C#");

3. 使用場景

  1. 若是是可變數量的參數,那麼很明顯只能使用apply;
  2. 若是要延遲調用某個函數,那麼只能使用bind;
  3. bind可以實現所謂的柯里化(function currying),即先傳一部分參數進去,使用的時候再傳另外一部分參數,這種場景下也只能使用bind。
相關文章
相關標籤/搜索