今天看原生js的时候看到了callapply,对这两个方法印象不是很清楚,只记得这两个方法很相似,作用大概是让A通过callapply能够调用B独有的方法,但是具体的使用方法已经模糊,所以网上查了资料重新理了一遍。

先看代码:

    function Createpeople(name, age) {
                this.name = name;
                this.age = age;
            }
    Createpeople.prototype.say = function() {
                console.log('Hello!My name is ' + this.name);
            }

    var Amy = new Createpeople('Amy', 18);
    Amy.say();  //Hello!My name is Amy

    var john = {
        name: 'john',
        age: 20
            }
    john.say();  //john.say is not a function
    Amy.say.call(john);  //Hello!My name is john
    Amy.say.apply(john);  //Hello!My name is john

Createpeople是一个构造函数,并且在原型中写入了一个say方法。我们用Createpeople创造了Amy对象,所以Amy理所当然地可以调用say方法。而john是我们手动创建的一个对象,所以john调用say方法理所应当会报错。那么如何让john能够调用say方法呢?那就要通过call方法或apply方法了。通过Amy.say.call(john),从输出结果来看john正确的调用了say方法,apply也同样。

为什么呢?原因就在于callapply在调用的时候会传入一个调用对象,即this,它们能将原来不指向传入对象的函数的this强行指向传入对象。可能这样说不是很明白,下面我来解释一下:

在其他方法执行的时候会默认传入一个调用对象,比如在Amy调用say方法的时候,默认传入的调用对象为Amysay方法作为Amy的一部分正常情况下因为正常情况下this只能指向Amy,但是通过callapply方法能让say方法的this强行指向传入的johnthis变成了john,理所当然,say方法就能正常执行了。

那么callapply有什么区别呢?

区别在于参数的传入方式不同。
举个例子:

    function add(a, b) {
                return console.log(a + b);
            }

    function sub(c, d) {
                return console.log(c - d);
            }

    sub.apply(add, [2, 3]);  //-1
    sub.call(add, 2, 3);  //-1
    add.apply(sub, [1, 2]);  //3
    add.call(sub, 1, 2);  //3

call方法参数是一个一个传的,而apply方法,除了this,其他参数是用数组的方式传的。
由于apply传数组这个特点,我们可以很方便地对数组进行某些操作,比如拼接两个数组:

        var list1 = [1, 2, 3];
        var list2 = [4, 5, 6];
        [].push.apply(list1, list2);  //6
        console.log(list1);  //[1, 2, 3, 4, 5, 6]

push方法可以传很多参数,但是不能传数组,正常情况下凭借数组只能够通过循环一个一个添加,但是apply正好需要把多个传入的参数打包成数组,所以正好满足了条件。