如何从一个无序数组中获取最大值或最小值?

js中的数组中并没有直接内置这样的方法,那我们就尝试为数组添加这样的方法。

Array.prototype.max=function(){
this.sort(function(a,b){ //函数可以被当成参数传递
return a-b
});
return this[this.length-1];
}
var arr=[1,3,2,5,11];
console.log(arr.max()); //11

Array.prototype.min=function(){
this.sort(function(a,b){ //js中函数是第一等国民
return a-b
});
return this[0];
}
var arr=[1,3,2,5,11];
console.log(arr.min()); //1

实现原理:首先把数组排序,然后根据索引取到最大值和最小值,代码非常直观、易懂。
但是js这门语言的强大之处就是它的灵活度超高,解决同一个问题有多种方法。

我们来看一个js的特性:apply

var values=[1,3,4,2,5,6,7];
var max=Math.max.apply(this,values);
console.log(max); //7
var min=Math.min.apply(this,values);
console.log(min); //1

实现原理:他山之石,可以攻玉。
数组没有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);
console.log(max); //7
var max=Math.min.call(this,1,3,4,2,5,6,7);
console.log(max); //1

实现原理和apply一样,区别是传参方式不同。
call方法是把参数一个一个传输,
而apply方法是把所有的参数放在数组,然后一次传输即可。
代码分析:
此处的this是执行上下文对象,换成任何值均可:this,null,undefined,0,Math都可以。
于是就有人针对此处this的理解,出了一道面试题:

var max=Math.max.call(10,1,3,4,2,5,6,7);
console.log(max); //7:ok 10:error
var max=Math.max.call(0,1,3,4,2,5,6,7);
console.log(max); //1:ok 0:error

出题者故意用一些值来试图混淆你的思维,因为此处传的第一个值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();
arr == [1,2,3] // true
var Nodelist = document.getElementsByTagName("*");
Array.prototype.slice.call(Nodelist) => Nodelist.slice() //自动转化成数组
Nodelist.slice() == Nodelist.slice(0) // 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中术士的生存秘籍——召唤术。
举例:
联盟战士想从暴风雪去达拉然,坐船加飞行太麻烦了,不如直接找法师开个门,多简单。
团队晚上开荒下副本,靠法师开门还得先集合,多麻烦。术士开个召唤术,就全部都拉过去了,多简单。