JS数组API方法重构封装总结

大前端基础之JS数组API总结及其方法重构封装
四.1、在JS中什么叫数组:
数组是数据的有序集合,每个值叫做一个元素,简称元,而每个元素在数组中有一个位置,以数字表示,称为索引,从0开始。js的数组是无类型的,数组元素可以是任意类型,同一个数组中的不同元素可能是对象或数组。数组元素的索引不一定要连续,元素之间可以有空隙,叫做稀疏数组 。每个数组都具有一个length属性。针对非稀疏数组,length属性就是数组元素的个数,针对稀疏数组,元素的length属性比所有元素的索引要大。
四.2、数组的构建方式
1)、字面量的创建;var arr=[ ];
2)、构造函数创建;var arr=new Array();
如果通过这个方式创建数组,参数仅有一个时,且这个参数是正整数的时候,不能是负数或者小数,则表示创建一个具备该正整数长度的数组,里面有这个长度若干个空元素,如果不是数值,这个数据就会作为该数组的第零个元素,长度为1
四.3 JS数组的特点;
1)arr.length 数组的长度,元素的个数,长度可被修改,最大下标为长度减1,仅记录下标的个数,不包含属性的数量
2)arr[arr.length]=20,在数组最尾部添加一个元素
3)在对象中属性名填入任何内容都会隐式转换成字符,在数组中所有的下标都会隐式转换成number(NaN),不能转换的就会默认添加为数组的属性名
4)数组不可以用点语法获取下标变量,但是可以用点语法获取属性
5)当给数组添加键值对的时候,数组长度并不会改变,调用的时候用点语法

四.4:数组的API;总的来说数组的API有以下几个,那下面小编就介绍几种在JS中经常用到的API和数组方法重构(其中arr参数表示为数组,item参数表示为元素,index为索引);
push()+pop(), shift()+unshift(), forEach(), map(), some(), every(), filter(), reduce()+reduceRight(), indexOf()+lastIndexOf(),join(), sort(), slice(), splice(), concat(), reverse(), Array.form(), Array.of(), find()+findIndex(), entries()+keys()+values(), includes()

四.1;push,unshift,pop,shift
1)push;在数组尾部添加一个或者多个元素,并且返回新数组的长度

重构push;(应用了参数列表,低版本ie不兼容)
function pushs(arr){
	for(var i=0,arLength=arr.length;i<arguments.length-1;i++){
		//在这里将原数组的长度赋值给变量固定,因为随着添加,arr的长度也会变大
		arr[arLength + i]=arguments[i+1];//在arr后面添加要添加的元素
	}
	return arr.length;//返回新数组的长度
}

2)unshift:在数组的头部增加一个或者多个元素,并且返回新数组的长度

重构unshiet;(应用了参数列表,低版本ie不兼容)
function unshifts(arr){
	var arr1=[];//为了获取原数组的开始值
	for(var i=arguments.length-1;i<arguments.length+arr.length-1;i++){
		// arr1[i]=arr[i-arguments.length-1];//分开写就不是一个整体了。所以整出来的数是undefined;
			arr1[i]=arr[i-(arguments.length-1)];
	}
	for(var j=0;j<arguments.length-1;j++){
			arr1[j]=arguments[j+1];//将要添加的元素添加在新数组的最前面
	}
	return arr1.length;//返回新数组的长度
}

3)pop; 删除数组最后一个元素,并且返回被删除的数值

重构pop;
function pops(arr){
    var item=arr[arr.length-1];//将数组最后一个元素保存
    arr.length--
    return item//返回被删除的元素
}

案例:清空数组
这样写,i会不断增大,length会不断减小,他们会相遇,所以不会全部删除
这样写并不能让数组清空
for(var i=0;i<arr.length;i++){ //之所有元素没有清空,是因为 i++ 了
arr.pop() }

这样写元素全部删除
	第一种方法:清空元素
   	 var len=arr.length //先把length固定起来,数组在怎么变他都不会变
  	 for(var i=0;i<len;i++){
   	 arr.pop()
   	}
    	 console.log(arr)

第二种方法:清空元素
   	 for(var i=1;i<arr.length;){
   	  arr.pop()
  	}
第三种方法:清空元素
   	while (arr.length>0) {
 	   arr.pop()
    		 }
 console.log(arr)

4)shift; 删除头部第一个元素,并且返回被删除的元素

重构shift;
function shifts(arr){
	var item=arr[0]//保存数组第一个元素
	for(i=0;i<arr.length;i++){;
		arr[i]=arr[i+1];//将数组元素都往前移一位
	}
	arr.length--;//删除数组最后一个元素,不进行这步的话数组最后一个元素还存在并为undefined
	return item;//返回被删除的长度
}

eg:

var arr=[1,2,3,4,5];
        var arr1=arr.push("s",6);
        var arr2=arr.unshift("a",10);
        var arr3=arr.pop();
        var arr4=arr.shift();
        console.log(arr1,arr2,arr3,arr4);//7 9  6 "a"//在这里,arr1和arr2返回新数组的长度,arr3和arr4返回被删除的元素

2;concat和join 数组的合并
1)concat。返回一个新数组,原来的数组不变化
var arr=arr1.concat(arr2,0,[“a”,“b”],-1);
如果直接使用,相当于复制 arr1=arr.concat();

重构concat;
function concats(arr,arr1,arr2,item){
    arr=[];//为返回新数组做准备
    for(i=0;i<arr1.length;i++){
        arr[i]=arr1[i];
    }
    for(j=0;j<arr2.length;j++){
        arr[arr1.length+j]=arr2[j];
    }//遍历数组arr1和arr2.
    arr[arr1.length+arr2.length]=item;//在已经将数组添加形成的arr数组,在其后面再拼接元素
    return arr;//返回拼接形成的新数组
}

2)join;返回指定的字符连接形成的新字符串;
如;arr=[1,2,3,4,5]
var str=arr.join("|"),默认为逗号 1|2|3|4|5;

重构join;
function joins(arr,item){
    str="";//为返回新字符串做准备
    if(item===undefined) item=","//用户未加item时,默认为逗号
    for(i=0;i<arr.length;i++){
        if(arr[i]===arr[arr.length-1]){
            str+=toString(arr[i]);//将数组最后一个元素的连接符号去掉
        }else{
            str+=toString(arr[i])+"item"'//将数组元素转化为字符串
        }
    }
    return str;//返回新字符串
}

四.3 splice;插入,删除,替换,返回被删除的元素组成的新数组;
arr.splice(从什么位置开始 可为负值表示由后向前,删除几个,替换的元素(一个或者多个))
var arr1=arr.splice() 这样会将arr数组清空返回给arr1
参数个数:
arr.splice(从什么位置开始 支持负数,删除几个,替换的元素)
arr.splice(1) 一个参数时从索引1开始截取到尾部
arr.splice(1,3) 从索引1开始,删除3个
arr.splice(1,3,6) 从索引1开始删除3个,并将6插入索引1中
arr.splice(1,3,6,4,8,9) 从索引1开始删除3个,并将6之后的元素插入索引1开始的位置。

重构splice方法
      //arr 为数组参数,index为索引(可以为负),arrNum为要删除的元素个数,后面可以跟需要添加的新元素。
      function splices(arr, index, arrNum) {
        //获取需要添加的元素个数(如果有的话)
        var arrArgumentsNum = arguments.length - 3;
        //设置delArr,用于以数组形式返回被删除的元素
        var delArr = [];
        //简单的判断,防止函数调用失败
        if (arr.length <= index) return 0;
        if (arrNum < 0) return 0;
        if (~index+ 1 > arr.length) return 0;
        //如果索引为负,在这里转为正(从后往前)
        if (index< 0) {
          index= index+ arr.length;
        }
        //for循环遍历删除元素,后面的元素前移
        for (i = 0; i < arr.length - index; i++) {
          if (i < arrNum) delArr[i] = arr[index+ i];
          arr[index+ i] = arr[index+ arrNum + i];
        }
        //删除多余元素
        arr.length -= arrNum;
        //如果需要插入元素,则进行下面操作
        if (arguments[3]) {
          arr.length += arrArgumentsNum;
          //循环让元素后移
          for (i = 0; i < arrArgumentsNum; i++) {
            arr[arr.length - i - 1] = arr[arr.length - arrArgumentsNum - i - 1];
          }
          //添加对应元素
          for (i = 0; i < arrArgumentsNum; i++) {
            arr[index+ i] = arguments[i + 3];
          }
        }
        return delArr;
      }

利用splice去重

Array.prototype.distinct=function(){ 
    for(var i=0;i<this.length;i++) {
        if(this.indexOf(this[i])!=i){
            this.splice(i,1);
            i--;
        }
    } 
    return this;
}
var arr=[1,1,2,3,4,5,6,2,3,4,5,6,7,1,2,3,4,5,6];
arr.distinct();//arr=[1, 2, 3, 4, 5, 6, 7]

案例:
1、去重(去掉重复的)
第一种方法

  var arr=[1,2,3,4,1,2,3,2,1,1,3,7,7,2,1,6,1,2,4,5,1,2,3];
  var arr1=[]
  	  for(var i=0;i<arr.length;i++){
      		  var item=arr[i]
      		  var bool=true
        	  for(var j=0;j<arr1.length;j++){
           		 if(arr1[j]===item){
              	  bool=false
                	  break
           		 }
      	             }
       	 if(bool){
          		  arr1.push(item)
       	       }
   	 }
   	 console.log(arr1)

第二种方法

 	   for(var i=0;i<arr.length;i++){
    		   var item=arr[i]
      	   for(var j=i+1;j<arr.length;j++){
          	    if(item===arr[j]){
             	   arr.splice(j,1) //从 j 位置开始,删除 1 个元素 
              	  j- -
          	               }
                       }
                  }
   	    console.log(arr)

四.4 slice;按指定位置截取复制内容,只能从前向后截取,第二个参数可以不写,默认到尾部;包括开始的位置,不包括结束的位置
arr.slice(从第几位开始(可以为负数,但是必须大于后面),到第几位结束)

重构slice
//第一种,比较绕
	function slices(array,start,end){
            var arr1=[];
            if(!array || !Array.isArray(array)) return arr1;
            if(end===undefined)    end=array.length;
            if(start =.= undefined)  start=0;//防止用户都没有填,返回默认值
            start=Number(start);
            end=Number(end);
            if(isNaN(start))  start=0;
            if(isNaN(end))    end=array.length;
            if(start<0)      start=array.length+start;
            if(end<0)       end=array.length+end;//当为负值时,从数组后面开始算
            for(var i=start;i<end;i++){
                arr1.push(array[i]);//将选中的元素添加到新数组里
            }
            return arr1;   //返回新数组
        }


//第二种,相对来说更好理解一点
			function slices(arr,startNum,endNum){
				if(startNum>endNum || startNum>arr.length) return;
				//如果不是从前向后或者初始值大于数组长度,直接返回
				var arr1=[];//为了返回新数组做准备
				if(endNum===undefined || endNum>arr.length) endNum=arr.length;
				if(startNum===undefined) startNum=0;
				//如果两个初始值都没有被定义,直接赋值为默认值
				if(endNum<0) endNum=arr.length+endNum;
				if(startNum<0) startNum=arr.length+startNum;
				//如果输入的初始值为负值,倒数开始计算
				if(startNum<0 && endNum>0){
					for(var i=endNum+1;i<startNum+1;i++){
						arr1.push(arr[i]);
					}
					//这个是当满足初始值为负,结束为正的情况而设,小编暂时也没有想出好点的方法
				}
				for(var i=startNum;i<endNum;i++){
					arr1.push(arr[i]);
				}
				//将截取范围的元素添加给arr1并且返回
				return arr1;
			}

slice的应用 复制

var arr=[1,2,3];
var copies = arr.slice(0);
arr.length=0;//arr数组删除所有元素
console.log(copies);
console.log(arr);

四.5 indexOf和lastindexOf;查找
find 返回数组中第一个符合条件的元素,findIndex返回索引(两中比较少用)

1)indexOf(查询元素,从什么位置开始),如果查到,返回该元素的下标。并且不会在继续查找。如果没有查到,则返回-1
当查询中有数组或者对象的时候,因为引用地址不同。所以无法查到
2)lastindexOf,和indexOf一样,只不过是从数组后面开始查找

案例:
1 、用indexOf去重

    var arr=[1,3,1,2,3,5,2,3,4,6];
    var arr1=[]
    for(var i=0;i<arr.length;i++){
        if(arr1.indexOf(arr[i])===-1){
            arr1.push(arr[i])
        }
    }
    console.log(arr1)

四.6 Array.from 将类数组转换成数组,拥有数组的方法
Array.of 把参数合并成一个数组返回,如果参数为空,则返回一个空数组

ES6中;arr=Array.from(类数组);
ES5中;arr=Array.prototepy.slice.call(类数组)

四.7数组的遍历;
forEach和map,for循环,for in
1)forEach 遍历数组,没有返回值
arr.forEach(function(item,index,arr){});

重构forEach
function forEachs(array,callBack){
 	if(!array || !Array.isArray(array)) console.error("forEachs is not function"); 
	for(var i=0;i<array.length;i++){ 
		callBack(array[i],i,array)
	};
	 // 遍历传入的数组,把数组的元素、下标、数组传入回调函数 
 } //不返回任何东西 }

2)map 遍历数组,返回和原数组长度相同的新数组,如果没有定义,直接为返回元素为undefined
arr.map(function(item,index,arr){});

map的重组
` 		function maps(array,callBack){
            if(!array || !Array.isArray(array))  console.error("maps is not  function");
            var arr1=[];//为返回新数组做准备
            for(var i=0;i<array.length;i++){
                if(array[i]===undefined)   continue;   //遍历过程中遇到undefined,跳出去这一次循环,后面继续,所以用continue;
                arr1[i]=callBack(array[i],i,array);//新数组的元素是回调函数中返回的结果 
            }
            for(var j=0;j<arr1.length;j++){
                return   arr1[j]===undefined ? undefined : arr1;   
            }  //如果新数组元素是undefined,返回值undefined,如果不是,返回新数组           
       	}`

3)for in 遍历数组,index为下标,arr[index]为属性值 for(index in arr){}
以上方法会跳过空元素;
4) for循环 for(i=0;i<arr.length;i++){}
1、for in不会遍历空元素,for会遍历空元素
2、for in可以遍历到数组的属性,for只能遍历数组所有下标,不能遍历属性
属性包含字符和下标(数字)

for in 循环和普通for循环的区别:
1、在循环数组时
for in 循环给循环变量赋值为 字符串类型,for in循环必须把所有的元素要循环一遍,
普通的for循环给循环变量赋值为 数字类型,普通的for的循环,可以控制循环哪些元素。更加灵活
2、循环对象:
for in循环可以循环对象
普通for循环,没法直接循环对象。
3、 用for in循环数组时,就是把数组当作了对象处理,下标就是键(键就是再其实啊,浏览器在处理数组时,会(可以)把它当作对象

四.8排序:按顺序排列 从小到大,或者从大到小
时间复杂度和空间复杂度
O(1) O(n) O(n log n)
时间复杂度 算法计算花费时间 花时间越少时间复杂度越小
空间复杂度 算法计算需要花费堆栈空间(内存)越多代表空间复杂度越高
在排序时,sort()方法会调用每个数组项的 toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值, sort()方法比较的也是字符串
1)冒泡排序;

function bubbleSort(arr){
	for(var i=0;i<arr.length-1;i++){
		for(var j=0;j<arr.length-1-i;j++){
			if(arr[j]>arr[j+1]) arr[j]=[arr[j+1],arr[j+1]=arr[j]][0];
			// 如果前面一项大于后面一项,两者交换
		}
	}
	return arr;
}

2)选择排序;

function choiceSort(arr){
	for(var i=0;i<arr.length-1;i++){
		for(var j=i,minIndex=i;j<arr.length-1;j++){
			//设定一个最小的下标用来比较
			if(arr[minIndex]>arr[j+1]) minIndex=j+1;
				// arr[i]>arr[j+1]的话就一直是arr[1]这个值在比较了,而我们希望遍历到数组最后,将最小的数的数组下标找到,所以arr[minIndex]<arr[j+1];
		}
			if(minIndex>i) arr[i] = [arr[minIndex],arr[minIndex]=arr[i]][0];
			//当mindex改变时,说明有最小下标,并将最小下标上的元素和当前元素交换
	}
	return arr;
}

3)str.charCodeAt()将字符串的第几项下标的元素转换成Unicode编码
如;var str=“cbd012” 长度为6,从为第0项;
str.charCodeAt(0);//将字符串的第0项转化为Unicode编码
4)Math.random()-0.5;将数组随机乱序
5)数组的排序方式 sort 只适用于数组
arr.sort(function(后一项(a),前一项(b))){
return a-b //从小到大
return b-a //从大到小
return Math.random()-0.5 //数组随机乱序,此时不需要填写参数
}
5)这种方法用于字符排序

   	 var arr=["d","e","b","a","c","h","j","i","k"];
       	 arr.sort(function(a,b){
            	// return a.charCodeAt(0)-b.charCodeAt(0)  //从小到大
           	 return b.charCodeAt(0)-a.charCodeAt(0);    //从大到小
       	 })
       	 console.log(arr)

四.9 some和every
1)some 查找数组是否有满足条件的元素,如果有就是返回true,不继续向后遍历,没有返回false
arr.some(function(item,index,arr){})

重构some
		function somes(arr,callBack){
            // callBack就是回调函数
            for(var i=0;i<arr.length;i++){
               if(callBack(arr[i],i,arr)) return true;
               //只要一个满足就返回true,并且退出函数不再执行
            }
            return false;
        }

2)every 查找数组中的条件每一个是否满足条件。有就返回true,只要有一就返回false;

重构every
		function everys(arr,callBack){
            for(i=0;i<arr.length;i++){
                if(!(callBack(arr[i],i,arr))) return false;
                //只要一个不满足就返回false
            }
            return true;
        }

四.10 filter和reduce及reduceRight
1)filter 将满足条件的元素返回一个新数组,“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。
arr.filter(function(item,index,arr){});

重构filter
		function filters(array,callBack){
            var arr1=[];//为返回满足条件的元素返回新数组做准备
            for (var i=0;i<array.length;i++){
                if(array[i]===undefined)   continue;
                if(callBack(array[i],i,array))  arr1.push(array[i]);  //如果这里用arr1[i]=array[i];  结果是[empty,2,empty,4......]
            }  //这是因为回调函数返回的是false true的布尔值,不满足条件的时候会直接跳过这个时候的i,这样arr1的不满足数位就是empty,但是用push,就能直接添加满足的元素。
            return arr1; //这个注释可以用来区分map和filter的区别,map返回的是赋值后的结果
        }

2)reduce,遍历数组,会将上一次的value返回给下一次的value
reduceRight()则从数组的最后一项开始,向前遍历到第一项。
arr.reduce(function(value,item,index,arr){} 初始值),如过初始值没有写的话,首先value会等于arr[0]
遍历从第一项开始,如果给了初始值,则初始值等于value,遍历从第0项开始

重构reduce
			function reduces(arr,callBack,value){
				//第一种  规规矩矩的,更不绕
				 if(value===undefined){
					value=arr[0];
					for(var i=1;i<arr.length;i++){
						value=callBack(value,arr[i],i,arr);
						console.log(value);
					}
				}else{
					for(var j=0;j<arr.length;j++){
						value=callBack(value,arr[j],j,arr)
						console.log(value)
					}
				} 
				
				//第二种
				var i=0;
				if(value===undefined){
					i=1
					value=arr[0];
				}
				for(;i<arr.length;i++){
					value=callBack(value,arr[i],i,arr)
					console.log(value)
				}
				
				return value;
			}

案例

	1、累积相加数组元素求和
           	      var arr=[10,3,4,7,3,5,8,9]; 
            	      var sum=arr.reduce(function(value,item){
         		    return value+item
      		 })
         		  console.log(sum);
	 2、希望求累积相加数组元素求和,在基数100的前提下,100就是初始值
	         var arr=[10,3,4,7,3,5,8,9]; 
               	         var sum=arr.reduce(function(value,item){
                  		  return value+item 
                	 },100)
                	 console.log(sum)

四.11 判断是不是数组,不能用typeof
1)ES6中;Array.isArray(arr),是就返回true,不是返回false
2)typeOf(arr)//只能判断数组的引用类型
3)Array.isArray()//ES5新增
4)instanceof 返回Boolean值 ,只能判断对象类型,基本数据类型不能判断,浏览器都兼容
语法:value instanceof 类
arr instanceof Array//返回布尔值 true

四.12 参数列表 arguments
arguments 伪数组;只能在函数中被调用,所有的列表(类数组,伪数组)都可以通过[下标]的方式调用。
arguments是实参中的列表,arguments.callee就是当前函数,如果该函数是回调执行的,arguments.callee.caller就是回调执行当前函数外的函数
注意:
arguments//参数列表 有长度length 伪数组,无法调用数组的方法
非严格模式中,如果形参改变了。里面的arguments[i]会随着改变
严格模式中,形参即使改变了,但是里面的arguments[i]不会改变

四.13 arr的方法reverse();数组元素倒序或者反转
var arr = [13, 24, 51, 3];
console.log(arr.reverse()); //[3, 51, 24, 13]
console.log(arr); //[3, 51, 24, 13](原数组改变)

四.14 entries/keys/values 都取/取键/取值

var arr=['a', 'b', 'c']
for(let key of arr.keys()){console.log(key)} //0,1,2                    
for(let value of arr.values()){console.log(value)} //a,b,c               
for(let [key, value] of arr.entries()){console.log([key,value])} //[0,'a'],[1,'b'],[2,'c']

ES6后:
四.15 includes判断数组是否包含某项,返回true/false
[1, 2, 3, 4, 5].includes(4) //true

四.16 fill() 填充

    var arr=[];
    arr.length=10;
    arr.fill(3);
    console.log(arr);//[3,3,3,3,3,3,3,3,3,3]

    // fill(值,从什么位置开始,到什么位置前结束),必须数组有长度,而且填充会覆盖
   	// var arr=new Array(5).fill(4);//[4,4,4,4,4]
   	// 填充覆盖的作用
     var arr=Array(10).fill(4);//[4,4,4,4,4,4,4,4,4,4]
     arr.fill(5,3,6);//包括前不包括后
    console.log(arr); //[4,4,4,5,5,5,4,4,4,4]

四.17 flatMap(function(item){}) 扁平化数组 返回一个合并的新数组
var arr=[[1,2,3],0,[4,5,6],[7,8,9]];
// flatMap扁平化数组
var arr1=arr.flatMap(function(item){
//这里的item是分散的arr中的值
//(3) [1, 2, 3]
// item 0
// (3) [4, 5, 6]
//3) [7, 8, 9]
return item
});
console.log(arr1); 合并起来的数组[1,2,3,0,4,5,6,7,8,9]

总结:就是敲敲敲哦,相对于ES6新出的方法来说封装其方法应该是对回调函数的理解,下周小编应该就是会和大家一起讨论讨论回调函数哦。不喜勿喷哦。

现在小编还有一个彩蛋哦。下面是一道经常被问到的面试题,虽然看起来简单,但是不小心还是会出错的哦,先别看答案试试吧;
_________________________面试题

    	 console.log(![]==[]);//true		//  !true==[]  false==""
		 console.log(![]==![]);//true		// !true==!true
		 console.log(![]==false);//true  	//false==false
		 console.log([]==true);//false		//""==true;  
		 console.log([]=="");//true			// ""==""   false==false
		 console.log(0==![]);//true			//false==!true
		 console.log(0==[]);//true			//false==false

解析:
因为![] 因为有! 就意味着将!后面的[]转换为布尔值
因为[]是对象类型,因此就会转换为true ,然后!true—>false
有!默认转换为布尔值,没有! 默认转换为""
[]=》bool=》!bool ![]=》false
false==[] 会将[]默认转换为"" false==""; true
false==""== 0
把[] 转换为字符窜的形式来判断;所有[] 为false
console.log([]==[]);//false
如果有!,那就需要先强制将!后面的内容转换为布尔值
嘻嘻,肿么样呢,小伙伴们有没有入坑哈?

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值