相信各位一定看到过Array.prototype.slice.call(arguments,1);这样的写法。(我是清楚的记得在看函数柯里化的时候遇到的,这儿我们不讨论它)
先查slice的定义:
上面的写法和我们看到MDN的例子看起来有很大的差别,其实殊途同归。
首先,简单向大家提及一下call,apply,bind的区别:
apply:(...).apply(context,[...args]); //绑定this之后,立即执行改变上下文之后的函数,获取结果。参数以数组形式传递
call:(...).call(context,arg1,arg2...) 绑定this之后,立即执行改变上下文呢之后的函数,获取结果。参数按函数定义的顺序排列。
bind: (...).bind(context),返回一个绑定了this之后的函数,也就说 需要手动调用。
其次,假如我们自己想在某个对象的原型对象上扩展一个方法,这儿我们以Array举例:
Array.prototype.isAllNumber=function(){ return this.every(x=>typeof x==“number”); }
//判断一个数组里面是否全部是数字。
根据刚才call的知识点可知道:
var array=new Array(1,2,3,4,5);
array.isAllNumber() //返回true,因为原型上已经定义了这样的方法。
接下来就是,既然isAllNumber是一个函数,函数就可以调用,关键在于怎样调用。
如果直接Array.prototype.isAllNumber() 肯定是会错误的,因为在这里面this是什么呢,我们不得而知。
但是 根据call的使用场景,我们可以手动为其指定this指向。
那么 稍作修改Array.prototype.isAllNumber.call([1,2,3,4,5,6]),因为这个函数没有参数,所以只需要指定this即可。
这样跟使用new 申明数组,再调用数组的方法本质即相同了。那么我们明白了Array.prototype.slice.call(arguments,1);
其实它的意思就是[...arguments].slice(1);// "...“是ES6的扩展运算符,arguments并不是一个真正的数组,使用这样的操作,它就变成了一个真正的数组。
于是知道这样的使用方法之后,我们便可以将一些实用的原型方法当静态方法实用了,ES5还为我们定义了以下7个方法:分别是 every,some,map,forEach,filter,reduce,reduceRight方法,具体的函数参数及用法大家可以参考MDN。