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的区别:
- forEach没法break
- 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点半,
如果觉得写的不错, 请点个赞吧!