来聊聊apply和call

今天在群里讨论的时候,看到有人问apply怎么使用,突然想起自己刚接触这个方法的时候,也是一样的摸不着头脑。

记得当时上网看了很多讲解,可实际用的时候还是感觉有些蒙蒙哒orz....   

 

后来想一想,也许是网上的说法有些太模式化了,让新手无法理解吧。

 

那今天咱们就来试试用比较通俗的方式来解析一下这个apply以及它的兄弟call。

 

先看看apply的定义:对象的继承、复制对象等等...

说的都对,但是对于新手来说,有些难以理解。

 

恩,那我们来通俗易懂的聊聊它

 

好 废话不多说,先上代码:

 

function add(){
    this.a = arguments[0];
    this.b = arguments[1];
};

function applyAdd(a , b , c){

    var B={
        c:c
    }

    add.apply(B,arguments);

    return B

}

var applys=applyAdd( 1 , 2 , 3 );

console.log(applys.a+applys.b+applys.c)  //输出6

 

 

很简单的一个加法运算。

这个加法运算实际上做了一件什么事情呢?

首先,我们创建一类:add   这个类有两个属性:this.a   this.b   

然后我们创建了另一个类:applyAdd    在这个类里我们使用了apply方法,然后给这个类定义了一个对象: B

然后我们返回这个对象。

接着给applyAdd类创建了一个新的实例:applys  请原谅我的命名比较没有创意,我说过我文笔不好嘛~~  ╮(╯▽╰)╭  

 

好啦,我们接着看   紧接着我输出了一遍applys的applys.a+applys.b+applys.c   

到这里我们要注意一下!:applys是applyAdd的实例, 但是applyAdd这个类并没有this.a和this.b! 也就是说正常来说我们这样输出应该返回NaN(undefined+undefined+3)

但是并没有,我们一样输出了6。 奥秘当然就在apply这个方法啦。

 

apply这个词翻译成中文是“使用”的意思。

但是我觉得这个翻译有些不太直观,我更倾向于把它叫做“抢劫”。。。

恩,既然是抢劫,首先要有一个被抢劫的倒霉蛋,还要有一个抢劫的劫匪嘛~

 

在这里我们的倒霉蛋自然就是add这个类啦,而劫匪就是B这个对象。

而劫匪就是apply的第一个参数:它必须要是一个对象(毕竟你不能说一串字符串是一个人嘛~)

但是这个劫匪,怎么说呢,脑子有些问题。  恩  这个体现在apply的第二个参数上:第二个参数是什么呢?是一个参数集合(一个数组)。

 

为什么说这个劫匪脑子有问题呢? 因为他会先给别人一些东西,然后再抢过来。。。 

恩,干这种脱裤子那啥的事,不就是脑子有问题么。。。 不过没办法,计算机就是个脑子跟正常人不太一样的东西~   ╮(╯▽╰)╭  

 

也就是说,这个时候  add里如果使用了参数,都会来自于apply第二个参数传入的东西。这里我们传入了applyAdd本身的参数进去,也就是最后传入的参数是[1,2,3]这样的一个数组。

当然,你也可以直接传一个数组[1,2,3]进去,效果是完全一样的。

然后我们在add内部把this.a和this.b用1和2来赋值,赋值完成后,还没等add乐呢,就一把抢过来~~

 

所以最后的实际运行过程是这样的:

function add(){
    this.a = arguments[0];//3. 哇!真好,竟然有人愿意给我钱~ 他一定是天使!  等等。。你要干嘛? 不要抢我的东西啊!!
    this.b = arguments[1];

    //1.我有两个袋子,但是都是空的。谁能给我点钱呢?
};

function applyAdd(a , b , c){

    var B={
        c:c
    }

    add.apply(B,arguments);//2.今天去抢劫add,不过他的两个袋子都是空的,没关系,我先给填上,然后再抢过来!哈哈哈,我真是太聪明啦~

    //4. B:哈哈哈  今天抢了两个袋子!收入不错

    return B

}

var applys=applyAdd( 1 , 2 , 3 );

console.log(applys.a+applys.b+applys.c)  // 5.B:数一数自己现在有多少钱! 6元!我真是太有钱了~

 

 

恩,大概就是这样一个过程 orz....

 

至于他的兄弟call,实际上跟apply的运行过程是完全一毛一样的,区别只在于:call的第二个参数,call实际上是可以有N个参数的,第一个参数一样是劫匪B,而后面的参数则是把apply的第二个参数从数组的形式变成了许多个独立的参数。 

别如你apply里的第二个参数是[1,2,3]  但是如果使用call的话,就要改成add.call(B,1,2,3)这样的形式。

 

至于怎么使用它们,以及何时使用,不在今天的讨论范围之内,我们改天再聊。

posted @ 2015-11-18 16:26  丸子爸爸Blue  阅读(345)  评论(1编辑  收藏  举报