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。
相关文章
相关标签/搜索