JS中的apply和call

<code class="hljs javascript has-numbering">JavaScript提供了apply和call两种调用方式来确定函数体中<span class="hljs-keyword">this</span>的指向,表现出来的特征就是:对象可以<span class="hljs-string">'借用'</span>其他对象的方法。
之前的几篇博客回顾了一些Web控件的一些开发方法,我们聊了如何实现一个自定义的组合框,也聊了一个相对复杂一点的地址控件的开发,从上一篇开始,开始聊一些JavaScript语言本身的话题,回顾了闭包和原型继承,今天我们就一起来聊聊apply和call这两种调用方式的前世今生。
当然,尽管主题在变,但是基于业务场景来剖析理论知识的写作风格不会变。
我们还是从一个生活中的例子说起:
小明家有水果,也有一台<span class="hljs-string">'果汁机'</span>,小红家也有水果,但是没有果汁机。有一天,小红也想把水果榨成果汁来喝,这时候,小红会怎么做呢?当然就是小红可以<span class="hljs-string">"借"</span>小明家的果汁机用一下,用完之后再回去,因为不用时放在自己家里还占地方,下次要用,再去借就是了,因为<span class="hljs-string">'互助'</span>是JavaScript社区的美德。
我们看看如何用JavaScript展示这种情况:

复制代码
<span class="hljs-keyword">var</span> xiaoming = {
    name:<span class="hljs-string">'小明'</span>,
    fruit:<span class="hljs-string">'橙子'</span>,
    makeJuice:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span>{</span>
        console.log( <span class="hljs-string">'正在榨:'</span> + <span class="hljs-keyword">this</span>.name + <span class="hljs-string">' 家的'</span> + <span class="hljs-keyword">this</span>.fruit + <span class="hljs-string">'汁!'</span>);
    }
}
<span class="hljs-keyword">var</span> xiaohong = {
    name:<span class="hljs-string">'小红'</span>,
    fruit:<span class="hljs-string">'苹果'</span>
}
xiaoming.makeJuice( );                 <span class="hljs-comment">//输出:正在榨:小明 家的橙子汁!</span>
xiaoming.makeJuice.apply( xiaohong );  <span class="hljs-comment">//输出:正在榨:小红 家的苹果汁!</span>
复制代码
apply方法最核心的意义就是这样,显然,如果某个函数体当中根本没有引用<span class="hljs-keyword">this</span>,那是不是也就失去了调用apply的意义?也并非如此,有时候还需要处理传入的参数。

进一步来看,如果调用的函数需要传递参数,那么调用apply时要如何处理呢?我们改进一下上面的例子,假设榨果汁的时候,需要传入参数:加水的量以及要榨多长时间。
这时候该如何使用apply呢?

复制代码
<span class="hljs-keyword">var</span> xiaoming = {
    name:<span class="hljs-string">'小明'</span>,
    fruit:<span class="hljs-string">'橙子'</span>,
    makeJuice:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">( water, time )</span>{</span>
        console.log( <span class="hljs-string">'正在榨:'</span> + <span class="hljs-keyword">this</span>.name + <span class="hljs-string">' 家的'</span> + <span class="hljs-keyword">this</span>.fruit + <span class="hljs-string">'汁,加水:'</span> + water + <span class="hljs-string">' mL,用时:'</span> + time + <span class="hljs-string">' 分钟。'</span>);
    }
}
<span class="hljs-keyword">var</span> xiaohong = {
    name:<span class="hljs-string">'小红'</span>,
    fruit:<span class="hljs-string">'苹果'</span>
}
<span class="hljs-keyword">var</span> task_info = [ <span class="hljs-number">500</span> , <span class="hljs-number">1</span> ] ;          <span class="hljs-comment">//把要传入的参数放到一个数组里</span>
xiaoming.makeJuice.apply( xiaohong , task_info ) ;  <span class="hljs-comment">//输出:正在榨:小红 家的苹果汁,加水:500 mL,用时:1 分钟。</span>
复制代码
【分析】
在使用apply方式使用一个函数时:

第<span class="hljs-number">1</span>个参数为thisObject,调用时采用传入的thisObject代替函数体中<span class="hljs-keyword">this</span>的指向。
第<span class="hljs-number">2</span>个参数传入一个数组,函数会用数组的值取代<span class="hljs-string">"参数列表"</span>。
回到上面的例子,相当于这样的场景:

小红:小明,你帮我榨一下苹果汁吧。
小明:可以啊,你把我家的榨汁机拿去用就可以了。
     用之前你得先想清楚<span class="hljs-string">'准备加多少水,要榨几分钟'</span>。
小红:好的。
小红把榨汁机拿来之后,就先把<span class="hljs-string">'加 500mL 水,榨 1 分钟'</span>的内容写到<span class="hljs-string">'纸'</span>上,准备好原材料之后,就按<span class="hljs-string">'纸'</span>上的信息操作榨汁机,避免手忙脚乱。用来写任务相关信息的<span class="hljs-string">'纸'</span>就相当于在apply方式调用时用来传递参数列表信息的数组。

说到参数列表,自然就想到了<span class="hljs-built_in">arguments</span>,在调用函数时,函数的运行时环境会自动产生一个变量<span class="hljs-built_in">arguments</span>指向实参列表。很多资料上都会说,<span class="hljs-built_in">arguments</span>是具有数组某些特性的<span class="hljs-string">'类数组'</span>(伪数组)。那么,当使用apply方式调用函数时,传入的第<span class="hljs-number">2</span>个参数是否可以是一个像<span class="hljs-built_in">arguments</span>这样的<span class="hljs-string">'类数组'</span>(伪数组)呢?
我们再构造一个场景来验证一下,最近小区又搬来了一位王奶奶,有一天王奶奶也想喝果汁,她知道小明家有榨汁机,本来想找小明帮忙,但是小明出差了。小明跟王奶奶说,你想好了要多少量的果汁以及想打多长时间,找小红帮忙就可以了。
现在,我们就来实现这样的场景,重点在于王奶奶求助小红的函数。

复制代码
<span class="hljs-keyword">var</span> wang = {
    name: <span class="hljs-string">'王奶奶'</span>,
    helpFromXiaohong: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">( water , time )</span>{</span>
        <span class="hljs-comment">//小红自己没有榨汁机,还是要使用小明的榨汁机,使用apply方式调用函数</span>
        <span class="hljs-comment">//王奶奶的要求 与 使用榨汁机时要准备的'任务内容'完全一样,</span>
        <span class="hljs-comment">//所以,这里直接传入arguments看看</span>
        <span class="hljs-comment">//至于水果嘛,小红当然不会向王奶奶要了,就用自己家的</span>
        <span class="hljs-comment">//于是,调用方式如下:</span>
        xiaoming.makeJuice.apply( xiaohong , <span class="hljs-built_in">arguments</span> ) ;
    }
}
wang.helpFromXiaohong( <span class="hljs-number">400</span> , <span class="hljs-number">2</span> ) ;   <span class="hljs-comment">//老人家喝的量不多,但是希望把水果打烂一点</span>

<span class="hljs-comment">//输出:正在榨:小红 家的苹果汁,加水:400 mL,用时:2 分钟。</span>
复制代码
发现和我们预期的内容是完全一样的,这就意味着,传入apply中的第二个参数,
也可以是一个<span class="hljs-string">'类数组'</span>,最常见的当然就是直接将<span class="hljs-built_in">arguments</span>传入作为第<span class="hljs-number">2</span>个参数。
<span class="hljs-string">'类数组'</span>的特征:

具有一个length成员,<span class="hljs-string">'表示'</span>包含的<span class="hljs-string">'元素个数'</span>。
能够用<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>等数字来检索它的成员。
到现在我们已经对apply调用方式有了一些认识,再回到我们日常的工作当中。我们经常会看到这样的调用方式:

<span class="hljs-keyword">var</span> w = <span class="hljs-built_in">Array</span>.prototype.shift.apply( <span class="hljs-built_in">arguments</span> );
这行代码表示什么意思也许大家都很清楚,就是将隐含的<span class="hljs-string">'类数组'</span><span class="hljs-built_in">arguments</span>的第一个参数值取出来,然后赋给变量w。

【思考】

<span class="hljs-number">1.</span> 为什么不直接用<span class="hljs-built_in">arguments</span>调用shift函数呢?

因为<span class="hljs-built_in">arguments</span>不是真正的<span class="hljs-string">'数组'</span>,从JavaScript的语言特征来说,<span class="hljs-built_in">arguments</span>仅仅是具有某些<span class="hljs-string">'数组特征'</span>的对象。它不是通过<span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>()的方式创建,它的原型链也没有链向<span class="hljs-string">'Array.prototype'</span>,所以不能直接使用shift()函数。
<span class="hljs-string">"靠,既然是语言自带的东东,为什么不直接设计成数组呢?搞得老子每次想用一下数组的相关方法还得拐个弯。"</span>
兄台息怒,其实这样想的人并不是您一个人,包括JavaScript的大师老道(Douglas Crockfod)也是这么想的,正所谓英雄所见略同。

<span class="hljs-number">2.</span> 如何理解<span class="hljs-keyword">var</span> w = <span class="hljs-built_in">Array</span>.prototype.shift.apply( <span class="hljs-built_in">arguments</span> );这一个语句呢?

我们了解到,根据apply的调用模式,它会用传入的第<span class="hljs-number">1</span>个参数代替函数体中的<span class="hljs-keyword">this</span>。从这里来看,就是用<span class="hljs-built_in">arguments</span>这个对象(具有<span class="hljs-string">'数组'</span>特征的特殊对象)代替了<span class="hljs-built_in">Array</span>.prototype.shift中的<span class="hljs-keyword">this</span>。

我们知道,如果用一个数组对象去调用shift是没有问题的。
例如:

console.log( [<span class="hljs-string">'A'</span>,<span class="hljs-string">'B'</span>,<span class="hljs-string">'C'</span>].shift() ) ; <span class="hljs-comment">//输出: A</span>
因为在[<span class="hljs-string">'A'</span>,<span class="hljs-string">'B'</span>,<span class="hljs-string">'C'</span>].shift()的调用过程中,没有传入任何参数,所以,可以推断<span class="hljs-built_in">Array</span>.prototype.shift的函数体中,肯定引用了<span class="hljs-keyword">this</span>。通过对<span class="hljs-keyword">this</span>.length 以及 <span class="hljs-keyword">this</span>[<span class="hljs-number">0</span>] 这种方式的处理来计算运算结果,

显然,这个特殊的对象<span class="hljs-built_in">arguments</span>进行<span class="hljs-built_in">arguments</span>.length 以及 <span class="hljs-built_in">arguments</span>[<span class="hljs-number">0</span>] 这样的使用方式是没有问题的,是能体现出它的<span class="hljs-string">'数组特征'</span>的,所以,通过调用<span class="hljs-built_in">Array</span>.prototype.shift.apply( <span class="hljs-built_in">arguments</span> );能够获得传入的第<span class="hljs-number">1</span>个参数值。

为了增加<span class="hljs-string">'画面感'</span>,我们把它放入前面王奶奶求助的函数中:

复制代码
<span class="hljs-keyword">var</span> wang = {
    name: <span class="hljs-string">'王奶奶'</span>,
    helpFromXiaohong: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">( water , time )</span>{</span>
        <span class="hljs-keyword">var</span> w = <span class="hljs-built_in">Array</span>.prototype.shift.apply( <span class="hljs-built_in">arguments</span> );
        console.log( <span class="hljs-string">'王奶奶想喝 '</span> + w + <span class="hljs-string">' mL的果汁。'</span> );  
        xiaoming.makeJuice.apply( xiaohong , <span class="hljs-built_in">arguments</span> ) ;
        }
    }
   wang.helpFromXiaohong( <span class="hljs-number">400</span> , <span class="hljs-number">2</span> ) ;  
复制代码
>期望输出:
王奶奶想喝 <span class="hljs-number">400</span> mL的果汁。
正在榨:小红 家的苹果汁,加水:<span class="hljs-number">400</span> mL,用时:<span class="hljs-number">2</span> 分钟。
>实际输出:
王奶奶想喝 <span class="hljs-number">400</span> mL的果汁。
正在榨:小红 家的苹果汁,加水:<span class="hljs-number">2</span> mL,用时:<span class="hljs-literal">undefined</span> 分钟。

【分析】

<span class="hljs-number">1.</span> 对于我们刚才想验证的结论,发现我们的假设是正确的。<span class="hljs-built_in">arguments</span>对象成功<span class="hljs-string">'借用'</span>了数组的shift函数,所以输出:王奶奶想喝 <span class="hljs-number">400</span> mL的果汁。
<span class="hljs-number">2.</span> 但是,在下面的调用中,居然输出的是:正在榨:小红 家的苹果汁,加水:<span class="hljs-number">2</span> mL,用时:<span class="hljs-literal">undefined</span> 分钟。
这个很好理解,shift函数的作用是:<span class="hljs-string">'弹出'</span>数组的<span class="hljs-string">'第1个元素'</span>并返回。这就意味着,经过<span class="hljs-keyword">var</span> w = <span class="hljs-built_in">Array</span>.prototype.shift.apply( <span class="hljs-built_in">arguments</span> );调用之后,<span class="hljs-built_in">arguments</span>中的内容也发生了变化,<span class="hljs-built_in">arguments</span>[<span class="hljs-number">0</span>]的值已经不是<span class="hljs-number">400</span>!

这也再一次说明:

apply的调用方式,除了替换函数体中的<span class="hljs-keyword">this</span>的指向之外,函数的其他逻辑没有发生任何变化。<span class="hljs-string">'借用'</span>的函数的效果,就跟对象自己拥有这个函数一样。
<span class="hljs-built_in">arguments</span>这个<span class="hljs-string">'类似数组'</span>,除了不是<span class="hljs-string">'原型继承自'</span><span class="hljs-built_in">Array</span>.prototype之外,其他的特征和数组也是一样一样的。
<span class="hljs-number">3.</span> 在刚才的场景下,如果你确实需要在调用xiaoming.makeJuice.apply( xiaohong , <span class="hljs-built_in">arguments</span> ) ;之前显示一下王奶奶想喝多少mL的果汁,直接调用<span class="hljs-keyword">var</span> w = <span class="hljs-built_in">arguments</span>[<span class="hljs-number">0</span>]; 就可以了,何必要<span class="hljs-string">'弹'</span>人家呢。

完整的例子如下:

复制代码
<span class="hljs-keyword">var</span> xiaoming = {
    name:<span class="hljs-string">'小明'</span>,
    fruit:<span class="hljs-string">'橙子'</span>,
    makeJuice:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">( water, time )</span>{</span>
        console.log( <span class="hljs-string">'正在榨:'</span> + <span class="hljs-keyword">this</span>.name + <span class="hljs-string">' 家的'</span> + <span class="hljs-keyword">this</span>.fruit + <span class="hljs-string">'汁,加水:'</span> + water + <span class="hljs-string">' mL,用时:'</span> + time + <span class="hljs-string">' 分钟。'</span>);
    }
}
<span class="hljs-keyword">var</span> xiaohong = {
    name:<span class="hljs-string">'小红'</span>,
    fruit:<span class="hljs-string">'苹果'</span>
}
<span class="hljs-keyword">var</span> wang = {
    name: <span class="hljs-string">'王奶奶'</span>,
    helpFromXiaohong: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">( water , time )</span>{</span>
        <span class="hljs-keyword">var</span> w = <span class="hljs-built_in">arguments</span>[<span class="hljs-number">0</span>];
        console.log( <span class="hljs-string">'王奶奶想喝 '</span> + w + <span class="hljs-string">' mL的果汁。'</span> );  
        xiaoming.makeJuice.apply( xiaohong , <span class="hljs-built_in">arguments</span> ) ;
        }
}
wang.helpFromXiaohong( <span class="hljs-number">400</span> , <span class="hljs-number">2</span> ) ;  
复制代码
最后,我们再补充说明一个特性:如果我们在使用apply调用方式时,第<span class="hljs-number">1</span>个参数传入的是<span class="hljs-literal">null</span>,但是,被<span class="hljs-string">'借用'</span>函数的函数体本身又使用了<span class="hljs-keyword">this</span>,那么,会不会报异常呢?因为直接写<span class="hljs-literal">null</span>.name这样的方式肯定是不行的。这里不卖关子,先把答案搁这里。答案是:不会报异常。
话说过了几天,王奶奶又想要喝果汁了,于是又给小明打电话,但是小明还在出差啊,于是小明又叫王奶奶去找小红帮忙,另外,小明也给小红打了个电话解释情况。这回接到小明的电话,小红可有点不乐意了,心想:<span class="hljs-string">'小明你是什么人啊?好名声你来拿,麻烦事我去做。'</span>尽管心里有些不爽,但是毕竟是热心肠的好女孩,王奶奶的忙还是帮了,不过,这一回,她可就没有拿自己家的水果去榨了,而是直接用了社区的水果。

回到王奶奶的求助函数,既然不用xiaohong家的水果,就不用传入xiaohong这个对象了,传一个<span class="hljs-literal">null</span>试试看。

xiaoming.makeJuice.apply( xiaohong , <span class="hljs-built_in">arguments</span> ) ;
修改为:

xiaoming.makeJuice.apply( <span class="hljs-literal">null</span> , <span class="hljs-built_in">arguments</span> ) ;
并且在代码的开头增加以下变量:

<span class="hljs-keyword">var</span> name = <span class="hljs-string">'社区'</span>;
<span class="hljs-keyword">var</span> fruit = <span class="hljs-string">'西瓜'</span> ;
这时候,输出的内容为:
王奶奶想喝 <span class="hljs-number">400</span> mL的果汁。
正在榨:社区 家的西瓜汁,加水:<span class="hljs-number">400</span> mL,用时:<span class="hljs-number">2</span> 分钟。

也就是说,如果第一个传入的参数是<span class="hljs-literal">null</span>,那么,在函数体内的<span class="hljs-keyword">this</span>会指向全局对象,在浏览器中就是window(在Chrome浏览器中是这样的效果)。很显然,如果函数体内用到了<span class="hljs-keyword">this</span>,而你在用apply方式调用它时,给它传一个<span class="hljs-literal">null</span>过去,这是一种<span class="hljs-string">'小红同学赌气'</span>的行为,不是一个好的习惯。

所以,对于apply调用方式,我们可以总结如下:

如果某个函数的函数体中明显使用了<span class="hljs-keyword">this</span>,那么,就应该传入一个明确的thisObj对象,并且这个对象应该包含相关的属性。类似于人家把<span class="hljs-string">'榨汁机'</span>借给你用已经不错了,你不能自己连水果也不准备吧?
如果某个函数就是<span class="hljs-string">'工具'</span>类型的,那么,在使用apply调用方式时,可以传入一个<span class="hljs-literal">null</span>作为thisObject。类似于<span class="hljs-string">'水果刀'</span>,使用时放在跕板上的水果是什么,它就切什么,跟拿着水果刀的人有什么没有半毛钱关系。
第二种情况的一个常见的使用场景是:函数的接口要求传入一个<span class="hljs-string">'参数列表'</span>,但你手头只有一个数组。
例如:希望你这样调用<span class="hljs-built_in">Math</span>.max( <span class="hljs-number">2</span> , <span class="hljs-number">10</span> , <span class="hljs-number">6</span> , <span class="hljs-number">1</span> ); 但是,你的手头只有[<span class="hljs-number">2</span>,<span class="hljs-number">10</span>,<span class="hljs-number">6</span>,<span class="hljs-number">1</span>]这样的一个数组。
-如果直接调用<span class="hljs-built_in">Math</span>.max([<span class="hljs-number">2</span>,<span class="hljs-number">10</span>,<span class="hljs-number">6</span>,<span class="hljs-number">1</span>]); 会输出<span class="hljs-literal">NaN</span>。因为<span class="hljs-built_in">Math</span>.max会认为第一个参数[<span class="hljs-number">2</span>,<span class="hljs-number">10</span>,<span class="hljs-number">6</span>,<span class="hljs-number">1</span>]根本就不是一个number。
-或者你可以这样:

<span class="hljs-keyword">var</span> test_array = [<span class="hljs-number">2</span>,<span class="hljs-number">10</span>,<span class="hljs-number">6</span>,<span class="hljs-number">1</span>];
<span class="hljs-built_in">Math</span>.max( test_array[<span class="hljs-number">0</span>] , test_array[<span class="hljs-number">1</span>] , test_array[<span class="hljs-number">2</span>] , test_array[<span class="hljs-number">3</span>] );
显然,这种方式是在练习打字,而不是在编程序^_^~~

[参数列表]和[数组],[数组]和[参数列表].......apply调用方式不就可以实现转换嘛,所以,我们可以这样操作:

 <span class="hljs-keyword">var</span> test_array = [<span class="hljs-number">2</span>,<span class="hljs-number">10</span>,<span class="hljs-number">6</span>,<span class="hljs-number">1</span>];
 console.log(  <span class="hljs-built_in">Math</span>.max.apply( <span class="hljs-literal">null</span> , test_array ) );  <span class="hljs-comment">//输出:10     </span>
输出了我们期望的结果:<span class="hljs-number">10</span>,是的,当时就是这样。

如果小红也不用社区的水果,直接用小明家的水果呢?那就不需要用apply方式调用了,直接用如下方式就可以了:

xiaoming.makeJuice( <span class="hljs-built_in">arguments</span> ) ; 
我们再来看一下这时候的王奶奶的求助函数:

复制代码
<span class="hljs-keyword">var</span> wang = {
name: <span class="hljs-string">'王奶奶'</span>,
helpFromXiaohong: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">( water , time )</span>{</span>
     <span class="hljs-keyword">var</span> w = <span class="hljs-built_in">arguments</span>[<span class="hljs-number">0</span>];
     console.log( <span class="hljs-string">'王奶奶想喝 '</span> + w + <span class="hljs-string">' mL的果汁。'</span> ); 
     xiaoming.makeJuice( <span class="hljs-built_in">arguments</span> ) ; 
  }
}
复制代码
看函数名称是helpFromXiaohong(从小红处获得帮助),实际上却是xiaoming.makeJuice(小明在提供帮助)。我们隐约感受到了某些<span class="hljs-string">'设计模式'</span>的感觉。关于设计模式,我们下次有空再聊。

今天的话题就聊到这里...

什么?还没有讲到call呢!

差点搞忘了,call方式和apply方式的差别主要体现在传入的形式参数的不一样,当采用call调用的时候,第<span class="hljs-number">1</span>个参数传入thisObject,第<span class="hljs-number">2</span>个参数以及后面的参数组成<span class="hljs-string">'实参列表'</span>传递给函数。
例如:
用apply方式调用时,我们会这样写:

<span class="hljs-keyword">var</span> task_info = [<span class="hljs-number">400</span>,<span class="hljs-number">2</span>];
xiaoming.makeJuice.apply( xiaohong , task_info ) ;
而用call方式调用时,我们会这样写:

xiaoming.makeJuice.call( xiaohong , <span class="hljs-number">400</span> , <span class="hljs-number">2</span> ) 
有人说,其实call调用方式就是使用apply方式实现的,类似于给<span class="hljs-built_in">Function</span>.prototype定义了一个成员函数call。JavaScript引擎到底如何实现,我们无从知晓,不过从JavaScript大神老道在他的书中只字未提call方式,可见我们只要理解了apply调用方式,并且知道apply和call在形式参数上的不同,也许就可以了。

形式参数上的差异,我们可以再用一个生活中的例子理解一下:

复制代码
小明经常去韩国出差,小红呢,经常委托小明帮忙在韩国带一些化妆品。
往常在小明出差前,小红都会把要买的化妆品写在一个清单里(相当于:apply模式把参数值放到一个数组里),
小明到了韩国的商场之后,只要拿出购物清单对照着买就可以了,相当于应用(apply)一下这个购物清单,这就是apply调用方式。

但是,有一次,小明因为出差时间短,就没有告诉小红,快回国到机场的时候,接到了小红的电话呼叫(call),没错,是小红call过来的。
<span class="hljs-string">"死鬼,去韩国出差也不说一声!是存心躲着本姑奶奶吗?!"</span>
<span class="hljs-string">"你听我解释,这不时间太短了,我马上就回国了,现在已经快到釜山机场了。"</span>
<span class="hljs-string">"现在在机场了也得给我买!你听好了我要买什么!"</span>
<span class="hljs-string">"好吧,我现在去给你买,你说一下你要买什么。"</span>
显然,小明手里头没有一个明确的购物清单,时间又那么紧,不可能先整理一张清单出来再去商场购买。
于是,小明就到商场里面,听着小红的电话,小红说一个,小明就把对应商品往购物车里放,这就是call方式。
复制代码
【总结】

在本文当中,我们解释了函数的apply调用方式的价值和使用方式,并结合常见的使用场景,解释了函数体中隐含的<span class="hljs-built_in">arguments</span>对象的一些特征,也解释了apply调用方式的一些注意事项,最后指出了apply调用方式和call调用方式的差异。
今天的话题就聊到这里,感谢诸位捧场。</code>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值