js call and apply
如何从一个无序数组中获取最大值或最小值?
js中的数组中并没有直接内置这样的方法,那我们就尝试为数组添加这样的方法。
Array.prototype.max=function(){ |
实现原理:首先把数组排序,然后根据索引取到最大值和最小值,代码非常直观、易懂。
但是js这门语言的强大之处就是它的灵活度超高,解决同一个问题有多种方法。
我们来看一个js的特性:apply
var values=[1,3,4,2,5,6,7]; |
实现原理:他山之石,可以攻玉。
数组没有max和min方法,但Math对象却内置了max和min方法。
数组做不到,但我们可以借助Math对象来做到。
代码多么简洁,不需要你去扩展数组,直接使用Math对象的方法即可。
values是一个数组,但传递给Math.max()的是数组values里的参数,而非数组本身。
得益于apply()方法,我们可以巧妙地获取数组里的参数,然后传给Math对象的max()方法。
我们来看一个js的特性:call
var max=Math.max.call(this,1,3,4,2,5,6,7); |
实现原理和apply一样,区别是传参方式不同。
call方法是把参数一个一个传输,
而apply方法是把所有的参数放在数组,然后一次传输即可。
代码分析:
此处的this是执行上下文对象,换成任何值均可:this,null,undefined,0,Math都可以。
于是就有人针对此处this的理解,出了一道面试题:
var max=Math.max.call(10,1,3,4,2,5,6,7); |
出题者故意用一些值来试图混淆你的思维,因为此处传的第一个值10或者0都是window的属性,
也就是说无论传什么值,this都指向window,而Math对象也是指向window,所以可以借用成功。
call的妙用:转化Nodelist为数组
通过document.getElementsByTagName选择的dom节点是一种类似array的array。
它不能应用Array下的push,pop等方法。我们可以通过:
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*")); |
这样domNodes就可以应用Array下的所有方法了。
很多人感到很奇怪了,为何此处就传了一个参数呢。
我们看看Array.prototype.slice在真实场景的用法是:
var arr = [1,2,3].slice(); |
综合这两个案例,相信你已经深入理解了apply和call的精髓了。
apply和call有两个用处:
1、改变this的指向;
2、传参形式的多样化
参考资料:(https://www.zhihu.com/question/20289071)
当你使用apply和call时,一定要搞清楚你到底要干什么?
如果你仅仅是想借用一个方法,那么this可以随便写;
如果你想要把自己变成另一个人,就需要改变this的指向;
也就是说apply和call有两种用途:
1、仅仅借用他人的方法;
2、把自己变成他人,继而拥有他的方法。
总结:js好比WOW;
Math.max.apply()好比WOW中法师的赚钱秘籍——传送门;
Math.max.call()好比WOW中术士的生存秘籍——召唤术。
举例:
联盟战士想从暴风雪去达拉然,坐船加飞行太麻烦了,不如直接找法师开个门,多简单。
团队晚上开荒下副本,靠法师开门还得先集合,多麻烦。术士开个召唤术,就全部都拉过去了,多简单。