目录
一,forEach
二,Filter
三,Map
四,Every
五,Some
六,Reduce
七,ReduceRight
总结
一,forEach
forEach方法是在Array.prototype上定义的方法,任意数组实例都可以直接调用该方法;
作用:循环遍历数组
形式:forEach(function(elem,index,self){},形参2);elem:数组的元素;index:索引值;self:数组本身;
实例:
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
var person = ['a','b','c','d','e'];
var li = document.getElementsByTagName('li');
function deal(elem,index,self) {
li[index].innerText = elem;
}
person.forEach(deal);
</script>
实例解析:person.forEach(deal);语句首先会进行一个for循环,循环次数为person的长度(即调用该方法数组的长度),在每一次循环过程中都会把当前索引值对应的数组属性,索引值,数组本身拿出来作为参数传入deal函数中,在执行deal函数;实现的最终效果就是把person数组中的每一项属性一一赋给li数组的每一项的innerText;
源码实现:
Array.prototype.myforEach = function (func) {
var len = this.length;
for(var i = 0; i < len ; i++){
func(this[i],i,this);
}
};
ps:在forEach()方法中通常传入的参数为一个,即想要执行的函数,但有一个不太常用的参数有时也会需要了解一下,第二个参数可以改变func函数的this指针,在常用的forEach中由于func是作为一个参数,并没有人去调用它,所以他的this指针是指向window的,当传入第二个参数后,就可以改变func函数的this指针了。
源码实现:
Array.prototype.myforEach = function (func) {
var len = this.length;
var _this = arguments[1];//令_this为调用myforEach方法时传入的第二个参数,arguments[]是实参列表
for(var i = 0; i < len ; i++){
//apply(a,[]);会改变this指针,传入的第一个参数的指针就是this指向的指针
//appli(),call()都可以改变this指针,区别在与传入的参数形式不同,apply以数组形式传入
func.apply(_this,[this[i],i,this]);
}
};
此时封装的方法与系统提供的forEach()方法一致;
二,filter
filter的含义为过滤,所以数组中的该方法所实现的功能也是过滤某一些元素;使用filter方法会返回一个新的数组且不改变原数组;
形式:filter(function(){},形参2);其中形参2与forEach作用一样,用于改变传入的函数的this指针的指向;
实例:
var person = ['a','b','c','d','e'];
var newArr = person.filter(function(elem,index,self){
if(elem == 'a'){
return true;
}else{
return false;
}
},obj);
console.log(newArr);
filter通过传入函数返回的值是true还是false来决定这个元素是否返回到新数组中;原理与forEach类似都会有一次遍历数组的过程;
源码实现:
var person = ['a','b','c','d','e'];
Array.prototype.myFilter = function (func) {
var arr = [];
var len = this.length;
var _this = arguments[1] || window;
for(var i = 0; i < len; i++){
func.apply(_this,[this[i],i,this]) && arr.push(this[i]);
//该语句的另一种写法为:
// if(func.apply(_this,[this[i],i,this])){
// arr.push(this[i])
// }
//或者使用三目运算符:
// func.apply(_this,[this[i],i,this]) ? arr.push(this[i]) : null;
}
return arr;
};
var newArr = person.myFilter(function(elem,index,self){
if(elem == 'a'){
return true;
}else{
return false;
}
},obj);
console.log(newArr);
效果系统提供的filter方法效果一致。
三,Map
映射作用,返回的是一个新的数组,不改变原数组;
形式:map(functio(){},形参2),其中形参2与forEach作用一样,用于改变传入的函数的this指针的指向;
例子:
var person = [{name:'jiangyr',age:21},{name:'xiaoming',age:25},{name:'lilei',age:10},{name:'hanmeimei',age:15}];
var newArr = person.map(function(elem,index,self){
elem.age +=10;
return elem;
})
console.log(newArr);
通过map方法队员组中每一个对象元素中的age属性实现+10的操作;
源码实现:
var person = [{name:'jiangyr',age:21},{name:'xiaoming',age:25},{name:'lilei',age:10},{name:'hanmeimei',age:15}];
Array.prototype.myMap = function (func) {
var arr = [];
var len = this.length;
var _this = arguments[1] || window;
for(var i = 0; i < len ; i ++){
if(func.apply(_this,[this[i],i,this])){
arr.push(this[i]);
}
}
return arr;
};
var newArr = person.myMap(function(elem,index,self){
elem.age +=10;
return elem;
})
console.log(newArr);
四,Every
基于遍历使用;判断该数组是否都符合条件,如果全部都符合返回true,若有一个不符合返回false,并且在遇到第一个不符合的元素时返回false后,程序就会停止;逻辑类似于&&运算符;
形式:every(function(elem,index,self){},形参2)
实例:
var person = [{name:'jiangyr',age:21},{name:'xiaoming',age:25},{name:'lilei',age:10},{name:'hanmeimei',age:15}];
var newArr = person.every(function(elem,index,self){
if(elem.age > 18){
return true;
}else{
return false;
}
})
console.log(newArr);
var person = [{name:'jiangyr',age:21},{name:'xiaoming',age:25},{name:'lilei',age:10},{name:'hanmeimei',age:15}];
var newArr = person.every(function(elem,index,self){
if(elem.age >= 10){
return true;
}else{
return false;
}
})
console.log(newArr);
源码实现:
Array.prototype.myEvery = function (func){
var flag = true;//作为判断标识
var len = this.length;
var _this = arguments[1] || window;
for(var i = 0; i < len; i ++){
if(!func.apply(_this,[this[i],i,this])){
flag = false;
break;//遇到不符合条件的即停止循环
}
}
return flag;
};
五,Some
同样基于遍历使用;功能与every类似,遍历数组中是否有任意一个符合条件的元素,如果有返回true,否则返回false;逻辑与 || 运算符类似;与every一样在遍历到符合条件的元素就会直接停止程序。
形式:some(function(){},形参2);
实例:
var person = [{name:'jiangyr',age:21},{name:'xiaoming',age:25},{name:'lilei',age:10},{name:'hanmeimei',age:15}];
var newArr = person.some(function (elem,index,self){
if(elem.age == 21){
return true;
}
},obj)
console.log(newArr);
源码实现:
var person = [{name:'jiangyr',age:21},{name:'xiaoming',age:25},{name:'lilei',age:10},{name:'hanmeimei',age:15}];
Array.prototype.mySome = function (func) {
var flag = false;
var len = this.length;
var _this = arguments[1] || window;
for(var i = 0; i < len; i ++ ){
if(func.apply(_this,[this[i],i,this])){
flag = true;
break;
}
}
return flag;
}
var newArr = person.mySome(function (elem,index,self){
console.log(index);
if(elem.age == 25){
return true;
}
},obj)
console.log(newArr);
六,Reduce
基于遍历使用;提供一个初始值,接收上一个元素执行回调函数(即传入的函数)的返回值,最后返回的是该初始值;
形式:reduce(function(previousValue,elem,index,self){},形参2);previousValue为初始值,传入的形参2会给function函数的precious参数赋初值;
如果不给previous赋初值,reduce会跳过索引值0,从索引值1开始执行;
var arr = [1,2,3,4,5];
var newArr = arr.reduce(function(pre,elem,index,self){
console.log(index);
return pre + elem;
})//未传入参数2,previousValue没有赋初值
console.log(newArr);
实例:设计一个方法,根据cookie的特性(以键值对的形式存在)把获得的cookie字符串改成对象的形式
var cookirStr = '_uuid=15DF509A-17F4-BF86-2C15-8C1F51BA099667377infoc; buvid3=749757B2-7573-4313-9F9D-2F692BCC979618551infoc; sid=jhlw4mkk; buvid_fp=749757B2-7573-4313-9F9D-2F692BCC979618551infoc; blackside_state=1; rpdid=|(u)~J|uR~~k0JuYu)uuYuku; LIVE_BUVID=AUTO2116181473568425; Hm_lvt_8a6e55dbd2870f0f5bc9194cddf32a02=1629384131,1630056390,1630062379,1630586535; fingerprint=448629250f67bb8a62d1ed190ea185c2; buvid_fp_plain=749757B2-7573-4313-9F9D-2F692BCC979618551infoc; DedeUserID=24455019; DedeUserID__ckMd5=2f4b078f15ab828b; bili_jct=03c0ee3e3a62758313ed936fb251b501; video_page_version=v_old_home; CURRENT_QUALITY=116; i-wanna-go-back=-1; b_ut=5; CURRENT_BLACKGAP=0; PVID=1; bp_video_offset_24455019=605949795895365900; bp_t_offset_24455019=605949795895365862; CURRENT_FNVAL=2000; innersign=0; b_lsid=B428FA27_17E1BF4258A'
function perseCookieStr(str){
//设计一个cookie字符串以自身键值对的特性转化为对象的属性名属性值的形式的方法
var obj = {};//返回的是一个对象
var arr = str.split('; '); //首先以'; '的形式进行分割并放入数组arr中.
arr.reduce(function(pre,cur,index,self){
//此时arr数组中的元素形式应该为_uuid=15DF509A-17F4-BF86-2C15-8C1F51BA099667377infoc形式,在遍历时在将该元素以'='分割,形成新的数组 此时该数组应该为[_uuid,15DF509A-17F4-BF86-2C15-8C1F51BA099667377infoc]
var temArr = cur.split('=');
pre[temArr[0]] = temArr[1];//将temArr数组的第一位作为对象的属性名,第二位作为其属性值
return pre;//作为返回值传给下一个pre
},obj)
return obj;
}
var cookieObj = perseCookieStr(cookirStr);
console.log(cookieObj);
源码实现:
Array.prototype.myReduce = function (func,preValue) {
var len = this.length;
var nextValue = preValue;
var _this = arguments[2] || window;
for(var i = 0;i < len ; i ++ ){
nextValue = func.apply(_this,[nextValue,this[i],i,this]);//每次执行后更新nextValue,作为下一次执行时的previous:
}
}
七,ReduceRight
功能与reduce一致,不过reduce从索引0开始遍历,而reduceRight从最后一位索引开始遍历
源码实现:
Array.prototype.myReduceRight = function (func,preValue) {
var len = this.length;
var nextValue = preValue;
var _this = arguments[2] || window;
for(var i = len;i >= 0 ; i ++ ){//只需要修改一下循环的顺序即可
nextValue = func.apply(_this,[nextValue,this[i],i,this]);//每次执行后更新nextValue,作为下一次执行时的previous:
}
}
小结
以上的方法都是对数组进行一次遍历,然后根据回调函数对数组元素进行相应的操作,底层思想是一样的,只是实现功能不同;以上方法仅对数组可用,对于类数组不可用;
可以使用扩展运算符或者Array.form()方法把类数组变成数组;
var divArr = document.getElementsByTagName('div');
var arr = [...divArr];//三个点就是扩展运算符
var arr2 = Array.from(divArr);