深入探索数组的神秘世界:手写实现13个必备API方法

前言

这篇文章将带大家一起手写下数组身上的其中的13种API方法,相关具体用法见于[MDN](Array - JavaScript | MDN (mozilla.org))。

1. forEach

定义和用法

forEach() 方法遍历数组中的每一项数据且都执行一次传入的函数,返回值为undefined

  • 语法forEach(callbackFn, thisArg)

  • 参数callbackFn为数组中每个元素执行的函数,thisArg可选。其中callbackFn函数接收3个参数------即数组当前项的值,索引,数组本身(item,index,arr)

  • 示例

javascript 复制代码
const arr=[
  {name:'花花',age:18},
  {name:'消息',age:18},
  {name:'钉钉',age:22}
]

arr.forEach((item,index,arr)=>{
  console.log(item);
})
//结果
{ name: '花花', age: 18 }
{ name: '消息', age: 18 }
{ name: '钉钉', age: 22 }

手写实现

javascript 复制代码
Array.prototype.my_forEach = function(callback){
  for(let i=0;i<this.length;i++){
  callback(this[i],i,this)
  }
}
arr.my_forEach((item,index,arr)=>{
  console.log(item);
})

2. map

定义和用法

map() 方法遍历数组,不修改原数组,使用传入的函数处理每个元素,并返回函数的返回值组成的新数组。

  • 语法map(callbackFn, thisArg)
  • 参数 :同forEach的参数一样
  • 示例
javascript 复制代码
const arr=[
  {name:'花花',age:18},
  {name:'消息',age:18},
  {name:'钉钉',age:22}
]
//map不修改原数组,有返回值,且回调函数要返回要的数据
let res=arr.map((item,index,arr)=>{
  return item.age*2
})
console.log(res);//[ 36, 36, 44 ]

手写实现

javascript 复制代码
Array.prototype.my_map=function(callback){
  let res=[]
  for(let i=0;i<this.length;i++){
   res.push(callback(this[i],i,this)) 
  }
  return res
}
let newarray=arr.my_map((item,index,arr)=>{
  return item.age*2
})
console.log(newarray);

3. every

测试一个数组内的所有元素是否都能通过指定函数的测试。它返回一个布尔值 。只要有一个函数返回结果为false则该结果为flase,只有全true结果才true

定义和用法

  • 语法every(callbackFn, thisArg)
  • 参数 :同forEach的参数一样
  • 示例
javascript 复制代码
const arr=[
  {name:'花花',age:18},
  {name:'消息',age:18},
  {name:'钉钉',age:22}
]
//判断数组中是否全部满足条件,是则true every有返回值
const res=arr.every((item,index,arr)=>{
  return item.age>=18
})
console.log(res);//true

手写实现

javascript 复制代码
Array.prototype.my_every = function(callback){
  const res=true
  for(let i=0;i<this.length;i++){
    if(!callback(this[i],i,this)){
      res=false 
      return res
    }
  }
  return res
}

const res=arr.my_every((item,index,arr)=>{
  return item.age>=18
})
console.log(res);

4. some

定义和用法

every()相反,只要有一个函数返回结果为true则该结果为true,只有全flase结果才false

  • 语法some(callbackFn, thisArg)
  • 参数 :同forEach的参数一样
  • 示例
javascript 复制代码
const arr=[
  {name:'花花',age:18},
  {name:'消息',age:18},
  {name:'钉钉',age:22}
]

const res=arr.some((item,index,arr)=>{
  return item.age>18
})
console.log(res); //true

手写实现

javascript 复制代码
Array.prototype.my_some = function(callback){
  for(let i=0;i<this.length;i++){
    if(callback(this[i],i,this)){
      return true
    }
  }
  return false
}

const res=arr.my_some((item,index,arr)=>{
  return item.age>18
})
console.log(res); //true

5. filter

定义和用法

用来筛选过滤的,将不符合条件的过滤出去,会返回一个新的对象数组且返回的是满足条件的数据,并不会改变原数组。

  • 语法filter(callbackFn, thisArg)
  • 参数 :同forEach的参数一样
  • 示例
javascript 复制代码
const arr=[
  {name:'花花',age:18},
  {name:'消息',age:18},
  {name:'钉钉',age:22}
]
//filter 有返回值(条件),过滤出来满足条件的数据
let res=arr.filter((item,index,arr)=>{
 return item.age>19
})
console.log(res); //[ { name: '钉钉', age: 22 } ]

手写实现

javascript 复制代码
Array.prototype.my_filter = function(callback){
  const res=[]
  for(let i=0;i<this.length;i++){
    callback(this[i],i,this) && res.push(this[i])
    //相当于
    // if(callback(this[i],i,this)){
    //   res.push(this[i])
    // }
  }
  return res
}
let res=arr.my_filter((item,index,arr)=>{
  return item.age>19
 })
 console.log(res);

6. find

定义和用法

找到满足条件的就返回第一个 满足条件数据的值,否则返回undefined

  • 语法find(callbackFn, thisArg)
  • 参数 :同forEach的参数一样
  • 示例
javascript 复制代码
const arr=[
  {name:'花花',age:18},
  {name:'消息',age:18},
  {name:'钉钉',age:22}
]
//find 找到满足条件的项 从左往右 找到就结束
const res=arr.find((item,start,arr)=>{
  return item.age>18
})
console.log(res);//{ name: '钉钉', age: 22 }

手写实现

javascript 复制代码
Array.prototype.my_find=function(callback){
  for(let i=0;i<this.length;i++){
    if(callback(this[i],i,this)){
      return this[i]
    }
  }
  return undefined
}
const res=arr.my_find((item,start,arr)=>{
  return item.age>18
})
console.log(res);

7. findIndex

定义和用法

找到满足条件的就返回第一个满足条件数据的下标 ,否则返回-1

  • 语法findIndex(callbackFn, thisArg)
  • 参数 :同forEach的参数一样
  • 示例
javascript 复制代码
const arr=[
  {name:'花花',age:18},
  {name:'消息',age:18},
  {name:'钉钉',age:22}
]

//找某一个元素下标 findIndex指找到满足条件的下标
let res=arr.findIndex((item,index,arr)=>{
  return item.age>18
})
console.log(res);//2

手写实现

javascript 复制代码
Array.prototype.my_findIndex=function(callback){
  for(let i=0;i<this.length;i++){
    if(callback(this[i],i,this)){
      return i
    }
  }
  return -1
}
let res=arr.my_findIndex((item,index,arr)=>{
  return item.age>18
})
console.log(res);

8. includes

定义和用法

用来判断一个数组是否包含一个指定的值,如果包含则返回 true,否则返回 false,返回值为布尔值

  • 语法includes(searchElement,fromIndex)
  • 参数searchElement 是需要查找的值,fromIndex 可选字段,指开始搜索的索引,如果 fromIndex < 0,则从末尾开始计数,但数组仍然从前往后进行搜索
  • 示例
arduino 复制代码
const arr=[1,2,'a',5,'c',9]
console.log(arr.includes('c',-3));//arr.length+(-3)

手写实现

kotlin 复制代码
Array.prototype.my_includes=function(val,index=0){
  if(index<0){
    index=this.length+index
  }
  for(let i=index;i<this.length;i++){
    if(this[i]===val)
      return true
  }
  return false
}
console.log(arr.my_includes('c',-3));

9. join

定义和用法

将一个数组的所有元素连接成一个字符串 并返回这个字符串,用逗号或指定的分隔符字符串分隔。

  • 语法join(separator)
  • 参数separator 可选字段,指定一个字符串来分隔数组的每个元素。
  • 示例
arduino 复制代码
const arr=['a', 'b', 'c']
console.log(arr.join(','));//a,b,c

手写实现

javascript 复制代码
Array.prototype.my_join=function(s=','){
  let str=''
  for(let i=0;i<this.length;i++){
    str+=`${this[i]}${s}`
  }
  return str.slice(0,str.length-1)
}

const a=arr.my_join('-')
//数组有splice 方法 字符串没有
console.log(a);//a-b-c

10. reduce

定义和用法

对数组中的每个元素按序执行一个提供的回调函数,每一次运行回调函数会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。

  • 语法reduce(callbackFn,initialValue)
  • 参数callbackFn 为数组中每个元素执行的函数,其接收4个参数------accumulator (上一次调用 callbackFn 的结果)、currentValue (当前元素值)、currentIndex (当前元素所在下标),array (数组本身);initialValue可选字段,第一次调用回调时初始化 accumulator 的值,可以实现累加的效果
  • 示例
javascript 复制代码
const arr=[
  {name:'花花',age:18},
  {name:'消息',age:18},
  {name:'钉钉',age:22}
]
//reduce接收多个参数(第2个参数为pre初始值) 里面的回调函数接收4个参数 pre若不给初始值则会当成第一个值
const sum=arr.reduce((pre,current,index,arr)=>{
  return pre+=current.age
},0,1,2,3) //1,2,3无意义 有用的只有前2个
console.log(sum);

手写实现

ini 复制代码
Array.prototype.my_reduce = function(callback,...arg){
  let pre,start=0
  if(arg.length){
    pre=arg[0]
  }else{
    pre=this[0]
    start=1
  }
  for(let i=start;i<this.length;i++){
    pre=callback(pre,this[i],i,this)
  }
  return pre
}

const sum=arr.my_reduce((pre,current,index,arr)=>{
  return pre+=current.age
},0,1,2,3) //1,2,3无意义 有用的只有前2个
console.log(sum);

11. fill

定义和用法

用一个固定值填充 一个数组中从起始索引(默认为 0)到终止索引(默认为 array.length)内的全部元素。它返回修改后的数组。

  • 语法fill(value,start,end)
  • 参数value 表示用来填充数组元素的值,start 可选字段,表示开始填充的下标,end 可选字段,表示填充的结束下标。
  • 示例
sql 复制代码
const arr=new Array(7).fill('hello',1,3) 
// 从数组下标1 开始 到3结束(不包含3)填充
console.log(arr);
//[ <1 empty item>, 'hello', 'hello', <4 empty items> ]

手写实现

sql 复制代码
Array.prototype.my_fill=function(value,start,end){
  if(start>=end) return this
  if(!start && start!==0){
    start=0
  }else if(start<0){
    start=this.length+start
  }
  end=(end <0?end+this.length:end)||this.length
  
  
  for(let i=start;i<end;i++){
    this[i]=value
  }
  return this
}
const arr=[2,23,53,26,67,34,65,4].my_fill('hello',-5,-3) 
console.log(arr);

12. splice

定义和用法

通过移除或者替换已存在的元素或添加新元素改变一个数组的内容,返回值为被删除元素的数组

  • 语法splice(start, deleteCount, item1, item2, itemN)
  • 参数start 开始索引 ,deleteCount可选字段,表示要删除的元素数量,item1...itemN可选字段,表示从start开始要加入到数组中的元素
  • 示例
bash 复制代码
let arr=['a','1',3,4]
console.log(arr.splice(-3,1,'aa','bb'),arr);//[ '1' ] [ 'a', 'aa', 'bb', 3, 4 ]

手写实现

scss 复制代码
Array.prototype.mySplice=function(...args){
  let res=[],i=0
  //不传参时
  if(!args.length)  return res

  //只传index参数
  if(args.length>=1){
    args[0]=Number(args[0])
    if(!isNaN(args[0])){
      if(args[0]<0){ //负数 表示从后计算所在位置
        args[0]=this.length+args[0]
      }
    }else{
      args[0]=0
    }
    if(args.length===1){
      for(i=this.length-1;i>=args[0];i--){
        let item=this.pop()
        res.unshift(item)
      }
    }
  }

  //传2个及以上的参数
  if(args.length>=2){
    args[1]=Number(args[1])
    if(!isNaN(args[1])&&args[1]>=0){
      let j=args[0],k=j+args[1],p=2 //j 代表第一个参数:起始下标,k 代表要删除元素个数所结束的下标
      if(k>=this.length){//要删除元素的长度大于起始下标后的元素的个数  全部删除
        let t=this.length-1
        res=[...this]
        while(t>=0){
          this.pop(this[t])   
          t--
        }
      }else{
        res.push(...this.slice(j,k))
        if(args.length===2){ //接收的参数为2个的时候
          while(k<this.length){
            this[j]=this[k]
            j++
            k++
          }
          this.length=this.length-args[1]
        }
        if(args.length>2){
          //第3个参数及以后的个数 小于 删除的个数
          if(args.length-2<=args[1]){
            while(p<args.length){
              this[j]=args[p] //替换要添加的数据
              p++
              j++
            }
            while(k<this.length){
              this[j]=this[k] //多出的位置 往前移动
              j++
              k++
            }
          this.length=this.length-args[1]+args.length-2
          }else{ //第3个参数及以后的个数 大于或等于 删除的个数
            let q=this.length
            while(q>k){
              this[q+args.length-3-args[1]]=this[q-1]
              q--
            }
            let cur=2
            while(cur<args.length){ //由于需要开辟新的空间留位置给其他用,所以要往后移动位置
              this[j]=args[cur]
              cur++
              j++
            }
          }
        }
      }

    }
  }
  return res
}

13. flat

定义和用法

数组扁平化,创建一个新的数组,并根据指定深度递归地将所有子数组元素拼接到新的数组中。也就是可以去除数组里括号的层数。

  • 语法flat(depth)
  • 参数depth 可选字段,指定要提取嵌套数组的结构深度,默认值为 1
  • 示例
ini 复制代码
let arr=[1, 2, 3, 4, [1, 2, 3, [1, 2, 3, [1, 2, 3]]]]
console.log(arr.flat(2));

手写实现

javascript 复制代码
Array.prototype.my_flat=function(depth=1){
  if(depth<0||!depth)
    return this
  let newArr=[].concat(this)
  while(depth>0){
    if(newArr.some(item=>Array.isArray(item))){
      newArr=[].concat.apply([],newArr)
    }else{
      break;
    }
    --depth
  }
  return newArr
}

let arr=[1, 2, 3, 4, [1, 2, 3, [1, 2, 3, [1, 2, 3]]]]
console.log(arr.my_flat(2));

结束语

本篇文章就到此为止啦,由于本人经验水平有限,难免会有纰漏,对此欢迎指正 。如觉得本文对你有帮助的话,欢迎点赞收藏❤❤❤。要是您觉得有更好的方法,欢迎评论,提出建议!

相关推荐
zqx_718 分钟前
随记 前端框架React的初步认识
前端·react.js·前端框架
惜.己35 分钟前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称1 小时前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色1 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2342 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河2 小时前
CSS总结
前端·css
NiNg_1_2342 小时前
Vue3 Pinia持久化存储
开发语言·javascript·ecmascript
读心悦2 小时前
如何在 Axios 中封装事件中心EventEmitter
javascript·http
BigYe程普2 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
神之王楠2 小时前
如何通过js加载css和html
javascript·css·html