数组API的实现与数组去重

1.数组6个api的实现

javascript中,有关数组的api实在太多,记性不好的很容易被搞晕。只有去了解这些api是怎么实现的,才能在用到他们的时候得心应手。

1.1 join

arr.join('char')是用传入的字符将数组中的每个元素连接在一起,形成字符串

let arr = [1,2,3];
arr.join('-')//‘1-2-3’
复制代码

实现join

Array.prototype.join = function(char){
	let result = this[0]||'';
    let len = this.length;
    for(let i=1;i<len;i++){
//注意这里的i是1,只有数组元素大于等于两个时,才返回用字符连接的元素
    	result+=char+this[i]
	}
    return result;
}
复制代码

1.2 slice

arr.slice(begin,end)从下标begin开始截取数组元素直到下标end(不包括end)

Array.prototype.slice = function(begin,end){
    let begin = begin || 0;//没有传入begin,则默认起始位置为0
    let end = end || this.length;//没有传入end,则默认截取到数组的最后一个元素
    let result = [];
    for(let i=begin;i<end;i++){
	//注意这里是i<end,slice的截取是左闭右开
        result.push(this[i]);
    }
    return result;
}
复制代码

slice可以截取出新的数组。所以很多人会用slice将伪数组转化为数组

arr = [].slice.call(arrLike)
复制代码

ES的新语法Array.from也可以将伪数组转化为数组

array = Array.from(arrLike)
复制代码

1.3 forEach

forEach是用来遍历数组的每一项的

arr.forEach(function(item,index,arr){
    //item是数组的每个元素
    //index是该元素的下标
    //arr就是数组本身
})
复制代码
Array.forEach = function(fn){
    for(let i=0;i<this.length;i++){
		fn.call(undefined,this[i],i,this);
        //call()第一个参数用来改变函数的上下文
        //后续的参数作为实参传进该函数
    }
}
复制代码

forEach与for的区别:

  1. forEach没法break
  2. forEach每次迭代都生成一个新的函数作用域

1.4 map

map用来操作改变数组的每一项,并返回新的数组

let arr = [1,2,3];
arr.map(function(item,index,arr){
	return item*2
})//[2,4,6]

Array.prototype.map = function(fn){
	let result = [];
    let temp;//用来储存每次被操作的元素
    for(let i=0;i<this.length;i++){
        if(i in this){//只操作数组中的元素,
            temp = fn.call(undefined,thiss[i],i,this)
            result.push(temp)
        }
    }
    return result;
}
复制代码

1.5 filter

filter是过滤器的作用,将数组中需要的元素筛选出来,返回数组

let arr = [1,2,4];
arr.filter(function(item,index,arr){
	return item%2==0
})//[2,4]

Array.prototype.filter = function(fn){
	let result = [];
    let temp;//用来判断过滤的元素是否合乎条件
    for(let i=0;i<this.length;i++){
        if(i in this){
			temp = fn.calll(undefined,this[i],i,this);
            if(temp){//如果合乎条件
                result.push(this[i])
            }
        }
    }
}
复制代码

1.6 reduce

reduce可以作为累加器

扫描二维码关注公众号,回复: 6433485 查看本文章
let arr = [1,2,3];
arr.reduce(function(prev,current,index,arr){
    //prev是上一次累加的结果,刚开始则等于传进来的初始化值
    return prev+current;
},10)//10是初始值,传给了prev
//结果 10+1+2+3=16

Array.prototype.reduce = function(fn,init){
    let result = init ||  0;//初始化值
    for(let i=0;i<this.length;i++){
        if(i in this){
            result=fn.call(undefined,result,this[i],i,this)
        }
    }
    return result;
}
复制代码

小总节:

map可以操作改变数组的每个元素,filter可以筛选出合乎条件的数组元素,reduce则是可以累加数组中的每个元素

1.7 reduce实现map

arr = arr.map(v=>v+1);
arr = arr.reduce((prev,cur){
                 prev.push(v+1)
				 return prev
                 },[])//这里传进初始化值为一个空数组
复制代码

1.8 reduce实现filter

arr = arr.filter(v=>v%2==0)
arr = arr.reduce((prev,cur){
                 if(cur%2==0) prev.push(cur)
				 return prev
                 },[])//这里也是传进一个空数组作为初始化的值
复制代码

小总结:

reduce可以实现map和filter的功能,初始化的值都是传入一个空数组

2.数组去重的4个方法

2.1冒泡

function unique(arr){
	let newArr = [];
    let len = arr.lenth;
    for(let i=0;i<len;i++){
		for(let j =i+1;j<len;j++){
            if(arr[i]==arr[j]){
                i++;//如果后面有重复的元素,则去遍历下一元素
                j=i;//出了if 会在内层for循环中 j++,
            }
        }
        newArr.push(arr[i])
    }
    return newArr;
}
复制代码

2.2 通过索引值

function unique(arr){
	let newArr = [];
    let len = arr.length;
    for(let i=0;i<len;i++){
        if(newArr.indexOf(arr[i])==-1){
            newArr.push(arr[i])
        }
    }
    return newArr;
}
复制代码

2.3 利用对象

function unique(arr){
    let newArr = [];
    let len = arr.length;
    let obj = {};
    for(let i=0;i<len;i++){
        if(!obj[arr[i]]){//看obj中是否有这个属性
           obj[arr[i]]=1;
            newArr.push(arr[i]);
        }
    }
    return newArr;
}
复制代码

2.4 利用排序

function unique(arr){
    arr.sort()//将数组排序
    let newArr = [];
    newArr[0] = arr[0];//将数组中的第一位给新创建的数组
    let len = arr.length;
    for(let i=1;i<len;i++){
        if(arr[i]!==newArr[newArr.length-1]){
		//被去重的数组中的元素只要不跟新创建的数组的最后一位相同
        //就可以将元素push进新数组
         	newArr.push(arr[i])
        }
    }
    return newArr;
}
复制代码

深度克隆对象

都写到数组去重了,就顺便把对象的深度克隆也写一写吧,哈哈

function deepClone(origin,target){
	target = target || {};
    let toStr = Object.prototype.toString;//用来判断是对象还是数组
    let arrStr = '[object Array]';
    //这是数组.toStr().call(数组)后的返回的内容
    for(let prop in origin){
        if(origin.hasOwnProperty(prop)){
            //hasOwnProperty判断该属性是在对象上而不是在原型链上
            if(origin[prop]!='null'&&typeof(origin[prop]=='object')){
                //typeof(数组/obj)的结果都是“object”
                if(toStr.call(origin[prop])==arrStr){
                    target[prop] = []
                }else{
                    target[prop] = {}
                }
                //当typeof得出的结果是object后,就必须深度克隆了
                deepClone(origin[prop],target[prop]);
            }else{
				target[prop] = origin[prop]
            }
            
        }
    }
    
}
复制代码

结语

因为本人水平有限,如果有错漏的地方,还请看官多多指正

本文作者胡志武,写于2019/6/05 凌晨1点半,

如果觉得写的不错, 请点个赞吧!

猜你喜欢

转载自blog.csdn.net/weixin_34360651/article/details/91394140
今日推荐