说点题外话
本文仅仅适用于新手,我是说很新的手哟,旨在和大家共同了解js的call和apply方法。笔者水平有限,文中不免会有疏漏,望大神轻喷。
开始说正事
apply 和 call 都是JavaScript 中的函数对象的方法,我们可以在任何的函数调用这两个方法。主要作用就是使得对象能够调用到本来不属于他的方法。
举两个栗子
假设我们有一个猫的对象:
var cat = { name:"cat", //名字叫cat run:function(){ //会跑 console.log("i can run"); }, jump:function(){ //还会跳墙 console.log(this.name+" can jump") } }
同时,还有它的小伙伴,狗狗对象:
var dog = { name:"dog", //名字叫狗狗 run:function(){ //会跑 console.log("i can run") }, bark:function(){ //还会叫 console.log(this.name+" bark loudly") } }
我们不难发现猫咪可以跳墙,但是狗狗可以叫。现在的情况特别紧急,紧急到了什么程度呢,狗狗想要跳墙了。可是它又不会跳,怎么办?好我们想到了要从猫咪那里把跳墙的方法暂时的学习过来过了风险时间再说:
这里就用到了我们的 apply;
cat.jump.apply(dog);
通过以上的方法,我们就能够让狗狗在着急的时候跳过墙头了。
我们可以得到结果,我们的狗狗同志成功跳墙成功啦。
同理,狗狗着急的同时猫咪也很紧张,这时候它想要大叫,但是嗓门不够高,怎么办?对啦,可以调用狗狗的这个方法的嘛。
dog.bark.apply(cat)
结果是猫咪也可以大声叫啦。
apply方法的原理
apply方法可以当作是一种方法的借调:也就是说把某个方法引用到不包含它的某个对象上。方法(函数)是用来被对象调用才能够执行的,而apply恰恰指向了调用当前方法的对象。初学者可能会误认为apply是对向继承了之前引用的方法。然而,并不是这样的。我们可以再次利用狗狗对象调用jump方法,得到的结果如下图所示:
dog.jump()
我们就能得出,并不是狗狗继承了跳墙的方法,只是对猫咪的跳墙能力进行了借调。
需要的参数
apply需要接收两个实参:
第一个实参是要调用函数的母对象,他是调用的上下文,如果在函数体内可以通过传this参数来获取对他的调用。在es5的严格模式中,apply的第一个参数会变为this值,即使你传入的是null或undefined。然而在es3和非严格模式中,传入的null和undefined都会被全局对象代替,而其他的原始类型值则会被相应的包装对象(wrapper object)代替。
第二个参数是函数调用时所传入的参数[可选填],必须是一个数组对象,或者在函数调用的时候以arguments对象的形式传入。
函数的call方法的作用和用法和apply完全是一样的,唯一的区别就是call方法调用时参数的写法不同,第一个参数依然是需要调取函数的对象,之后的参数则是将调用函数需要的实参一一列举出来,而不是放入一个参数数组中了。
再来两个栗子
创建一个小盆友李华(会说英语)。
var lihua = { speak:function(){ console.log("i can speak english") } }
他有一个好盆友圈圈(会做加法)。
var quanquan = { add:function(num1,num2){ return num1+num2; } } console.log(lihua.add(1,2))
期末考试的时候李华要考数学了,肿么办?
代码如下:
使用apply方法
console.log(quanquan.add.apply(lihua,[2,3]));
执行语句后
李华成功的计算出了 2+3 = 5;
使用 call 方法:
细心的小伙伴不难发现,当我们使用 call 方法和 apply 给李华添加算数技能的唯一区别就是参数的格式有一点变化.对啦!!!!
当使用 apply 方法的时候,函数的参数要以一个参数数组的方式传递进来.但是使用 call 的话就不用这样了.我们可以直接将参数写在对象名称的后边就OK了.是不是很方便?
从此,李华的高数就没有挂过科........(当然,圈圈是挂过的)
剩下的就是一场英语考试了.小伙伴们,有没有办法,让圈圈通过英语考试就看你们的啦.....
第一篇文章,欢迎大家批评指正