「JS系列之基础整理」扫盲(3)-数组方法专题

312 阅读11分钟

大家好!在前端关于数组的运用的,一般来说相对比较简单,我们对数据结构的处理一般都是放在后端的,当然,当自己的模块设计不是定制化的时候可能需要多一些数据结构的处理,官方给我们提供了30多种关于数组操作的方法,极大的方便了我们获取数据以及处理数据结构。本期呢,就是以实现数组方法这条路子,更好的理解并使用数组的相关方法,方便我们的开发。当然,自己实现的思路必然不是最优解,也希望大家不吝赐教!我是阿树,让我们开启本期的探索吧!

一、call/apply/bind

  • call() / apply():调用函数,指定函数中的this为第一个参数的值
  • bind(obj):返回一个新的函数,新函数内部会调用原来的函数、且this为第一参数的值 这里先大致说一下这三个方法,因为在下面数组方法的实现中很多都使用了其来改变this的指向,这里不深入探讨,this指向的问题牵扯面相对较广,比如原型链等,我们本期主要以数组的方法为主。

1.1 call

1.1.1 实现思路

判断是否有对象参数传入 没有则指向 window
给对象添加一个方法
对象使用此方法
将对象的该方法删除

1.1.2 代码实现

Function.prototype.myCall = function (obj, ...args) {
  obj = obj || window
  obj.tempFn = this
  obj.tempFn(...args)
  delete obj.tempFn
}  

1.2 apply

1.2.1 实现思路

判断是否有对象参数传入 没有则指向 window
给对象添加一个方法
对象使用此方法
将对象的该方法删除

1.1.2 代码实现

Function.prototype.myApply = function (obj, ...args) {
  obj = obj || window
  obj.tempFn = this
  obj.tempFn(...args)
  delete obj.tempFn
}  

1.3 bind

1.3.1 实现思路

返回一个方法
返回的方法使用箭头函数 避免 this指向更改
返回的方法函数体与call/apply一致即可

1.3.2 代码实现

Function.prototype.myBind = function (obj, ...args) {
  return (...args2) => {
    this.apply(obj, ...args, ...args2)
  }
}  

二、自定义实现数组方法

2.1 lastIndexOf()

2.1.1 功能概述

自定义方法名: myLastIndexOf()
功能: 查找的字符串最后出现的位置
参数: searchvalue->必需:规定需检索的字符串值
参数: start->非必需:规定检索的起始位置,不传则从最后一位开始
返回值: 字符串中首次出现的下标,没有匹配则返回 -1
是否改变原数组:

2.1.2 实现思路

  • 不传参数 返回 -1
  • 不传起始位置,从 最后一位 开始检索 匹配返回相应下标并阻断流程,否则返回-1
  • 传入非数字起始位置,返回 -1
  • 传入起始位置浮点型 向下取整
  • 传入起始位置 小于0 返回-1
  • 传入起始位置 大于 数组的长度 从 最后一位 开始检索
  • 注意: parseInt(-0.2) = -0

2.1.3 自定义实现

Array.prototype.myLastIndexOf = function (searchVal, start) {
  if(!searchVal) return -1

  let nowStart
  if (start && (typeof start === 'number')) {
    nowStart = parseInt(start)
    if(nowStart === -0) nowStart = 0 // 容易忽略的点
    if(nowStart < 0)  return -1
  } else if (start && (typeof start !== 'number')) return -1 
  else nowStart = this.length - 1

  for(; nowStart > 0 ; nowStart--) {
    if(this[nowStart] === searchVal) return nowStart
  }
  return -1
}

2.1.4 测试

let arr = [1, 18, 30, 23, 15, 22, 23]
console.log('------不穿参数对比(官方->自定义)--------')
console.log(arr.lastIndexOf())
console.log(arr.myLastIndexOf())
console.log('------不穿起始位置对比(官方->自定义)--------')
console.log(arr.lastIndexOf(23))
console.log(arr.myLastIndexOf(23))
console.log('------传入整型起始位置对比(官方->自定义)--------')
console.log(arr.lastIndexOf(23, 4))
console.log(arr.myLastIndexOf(23, 4))
console.log('------起始位置小于0对比(官方->自定义)--------')
console.log(arr.lastIndexOf(23, -6))
console.log(arr.myLastIndexOf(23, -6))
console.log('------起始位置大于数组长度对比(官方->自定义)--------')
console.log(arr.lastIndexOf(23, 8))
console.log(arr.myLastIndexOf(23, 8))
console.log('------起始位置非数字对比(官方->自定义)--------')
console.log(arr.lastIndexOf(23, 'a'))
console.log(arr.lastIndexOf(23, {a: 1}))
console.log(arr.myLastIndexOf(23, 'a'))
console.log('------起始位置浮点型对比(官方->自定义)--------')
console.log(arr.lastIndexOf(23, 4.6))
console.log(arr.myLastIndexOf(23, 4.6))

2.2 join()

2.2.1 功能概述

自定义方法名: myJoin()
功能: 把数组中的所有元素转换一个字符串
参数: 非必须
返回值: 转换后的字符串
是否改变原数组:

2.2.2 实现思路

  • 不传参数 默认以 ‘,’ 拼接
  • 传空字符串 元素直接相连
  • 传其他参数 以传入标记 为连接符拼接

2.2.3 自定义实现

Array.prototype.myJoin = function (tag) {
  let nowTag
  if(typeof tag === 'undefined') nowTag = ','
  else nowTag = tag
  let changeResult = ''
  if(this.length !== 0) {
    for(let i = 0; i < this.length; i++) {
      if(i + 1 === this.length) changeResult += this[i]
      else {
        changeResult = changeResult + this[i] + nowTag
      }
    }
  }
  return changeResult
}

2.2.4 测试

let arr = [1, 18, 30]
let arr1 = []
console.log('------不穿参数对比(官方->自定义)--------')
console.log(arr.join())
console.log(arr.myJoin())
console.log('------穿参数对比(官方->自定义)--------')
console.log(arr.join(''))
console.log(arr.myJoin(''))
console.log('------穿参数对比(官方->自定义)--------')
console.log(arr.join('-'))
console.log(arr.myJoin('-'))
console.log('------穿参数对比(官方->自定义)--------')
console.log(arr.join(' - '))
console.log(arr.myJoin(' - '))
console.log('------数组长度为0(官方->自定义)--------')
console.log(arr1.join(' - '))
console.log(arr1.myJoin(' - '))

2.3 sort()

2.3.1 功能概述

自定义方法名: mySort()
功能: 数字数组排序
参数: function()
返回值: 排序后的数组
是否改变原数组:
注意: 该方法仅实现数字数字的大小排序,并未实现官方sort的功能,在后续整理算法的时候会进一步完善该方法

2.3.2 实现思路

  • 冒泡排序
  • 根据掺入的函数返回值,来决定大小排序方式
  • 含有非数字类型元素 阻断流程,给出无法排序提示
  • 元素对调后立即跳出本次循环

2.3.3 自定义实现

Array.prototype.mySort = function (callback) {
  for (let  i = 0;  i < this.length - 1; i++) {
    for (let j = i + 1; j < this.length; j++) {
      if (typeof this[j] !== 'number' || typeof this[i] !== 'number') return '数组含有非数字类型元素,无法排序'
      let temp
      if (callback(this[i], this[j]) > 0) continue
      else {
        temp = this[i]
        this[i] = this[j]
        this[j] = temp
      } 
    }
    
  }
  return this
}

2.3.4 测试

let arr = [1, 18, 30, 0, 23, 15]
let arr1 = ['ss' ,1, 18, 30, 0, 23, 15]
console.log(arr.mySort((a, b) => a - b))
console.log(arr.mySort((a, b) => b - a))
console.log(arr1.mySort((a, b) => b - a))

2.4 splice()

2.4.1 功能概述

自定义方法名: mySplice()
功能: 添加或删除数组中的元素
参数: index,删除或这添加的起始下标
参数: nums,删除的个数
参数: others,插入的元素
返回值: 删除的元素组成的数组
是否改变原数组:
注意: 该方法并不是最简化还可优化

2.4.2 实现思路

  • 根据arguments获取index nums
  • 根据index确定是否需要操作数组 不需要 返回 []
  • 实现index有值 不传nums 情景
  • 实现index有值 nums大于 length - index 的 情景
  • 实现index有值 nums小于 length - index 的 情景
  • 实现index有值 nums有值,有others插入值 的 情景
  • 这里主要是细分场景,具体的场景实现相对简单,大家可以捋一下如果有感觉难梳理的,请留言,我这边下次画个流程图给大家参考

2.4.3 自定义实现

Array.prototype.mySplice = function () {
  let nums = typeof arguments[1] === 'number'? arguments[1] : ''
  let index = typeof arguments[0] === 'number'? arguments[0] : ''
  let result = []
  if (!index ||(index && typeof index !== 'number')) return result
  if (index && nums === '') {
    for (let i = index; i < this.length; i++) result[result.length] = this[i]
    this.length = index
  }else if(nums && typeof nums === 'number') {
    if (nums >= this.length - index -1) {
      for (let i = index; i < this.length; i++) result[result.length] = this[i]
      this.length = index
    } else {
      for (let i = index; i < index + nums; i++) {
        result[result.length] = this[i]
      }
      for (let t = index; t < this.length - nums; t++) {
        this[t] = this[t + nums]
      }
      this.length = this.length - nums
    }
  }

  if (arguments.length > 2) {
    let endArr = []
    for (let k = index; k < this.length; k++) endArr[endArr.length] = this[k]
    this.length = index
    for (let m = 2; m < arguments.length; m++) this[this.length] = arguments[m]
    for (let n = 0; n < endArr.length; n++) this[this.length] = endArr[n]
  }
  return result
}

2.4.4 测试

let arr = [1, 18, 30, 0, 23, 1, 18, 30, 0, 23, 1, 18, 30, 0, 23, 15]
let arr1 = [1, 18, 30, 0, 23, 1, 18, 30, 0, 23, 1, 18, 30, 0, 23, 15]
console.log('--------不传参数对比 官方-->自定义-----------')
console.log(arr.splice())
console.log(arr1.mySplice())
console.log('原数组arr', arr)
console.log('原数组arr1', arr1)

console.log('--------参数index为4 不传nums 对比 官方-->自定义-----------')
console.log(arr.splice(12))
console.log(arr1.mySplice(12))
console.log('原数组arr', arr)
console.log('原数组arr1', arr1)

console.log('--------参数index为4 传nums = 0 对比 官方-->自定义-----------')
console.log(arr.splice(4, 0))
console.log(arr1.mySplice(4, 0))
console.log('原数组arr', arr)
console.log('原数组arr1', arr1)

console.log('--------参数index为4 传nums > length - index -1 对比 官方-->自定义-----------')
console.log(arr.splice(4, 4))
console.log(arr1.mySplice(4, 4))
console.log('原数组arr', arr)
console.log('原数组arr1', arr1)

console.log('--------参数index为4 传nums > length - index -1 对比 官方-->自定义-----------')
console.log(arr.splice(2, 2))
console.log(arr1.mySplice(2, 2))
console.log('原数组arr', arr)
console.log('原数组arr1', arr1)

console.log('--------参数index为4 传nums > length - index -1 ,传入插入值 对比 官方-->自定义-----------')
console.log(arr.splice(2, 2, 'haha', 'hehe'))
console.log(arr1.mySplice(2, 2, 'haha', 'hehe'))
console.log('原数组arr', arr)
console.log('原数组arr1', arr1)

2.5 some()

2.5.1 功能概述

自定义方法名: mySome()
功能: 检测数组中的元素是否满足指定条件
参数: function() 必须
参数: obj 非必须
返回值: true false
是否改变原数组:
注意: 当需要传入obj的时候,方法必须是匿名函数,不能是箭头函数,因为箭头函数没有this

2.5.2 实现思路

  • function 不传 抛出错误
  • 当数组为空时,直接返回false
  • 当传入 obj时 ,需要改变 this的指向,也就是调用callback的是obj不再是 window使用call解决
  • 没有 obj 传入的时候 直接调用 callback
  • 根据 callback的返回值 ,如果为true 直接返回true 并阻断流程
  • 如果循环结束 callback 返回值 依然为false 返回 false

2.5.3 自定义实现

Array.prototype.mySome = function (callback, obj) {
  if(!callback) throw (`${callback} is not a function`)
  for (let i = 0; i < this.length; i++) {
    if(obj){
      if(callback.call(obj, this[i], i, this)) return true
    } else {
      if (callback(this[i], i, this)) return true
    } 
  }
  return false
}

2.5.4 测试

let arr = [1, 'aa', 'name']
let obj = {
  name: 'aa'
}
let arr1 = []


console.log('--------传入function 官方-->自定义-----------')
console.log('官方----->', arr.some((value, index) => {
  return value === 'aa'
}))
console.log('自定义----->', arr.mySome((value, index) => {
  return value === 'aa'
}))

console.log('--------传入function, obj 官方-->自定义-----------')
console.log('官方----->', arr.some(function (value, index){
  console.log(this)
  return value === this.name
}, obj))
console.log('自定义----->', arr.mySome(function (value, index){
  return value === this.name
}, obj))

console.log('--------数组为空 官方-->自定义-----------')
console.log('官方----->', arr1.some(() => {
  return 1
}))
console.log('自定义----->', arr1.mySome(() => {
  return 1
}))

console.log('-------不传function 官方-->自定义-----------')
console.log('官方----->', arr.some())
console.log('自定义----->', arr.mySome())

2.6 every()

2.6.1 功能概述

自定义方法名: myEvery()
功能: 检测数组所有元素是否都符合指定条件
参数: function() 必须
参数: obj 非必须
返回值: true false
是否改变原数组:
注意: 当需要传入obj的时候,方法必须是匿名函数,不能是箭头函数,因为箭头函数没有this

2.6.2 实现思路

  • function 不传 抛出错误
  • 当数组为空时,直接返回true
  • 当传入 obj时 ,需要改变 this的指向,也就是调用callback的是obj不再是 window使用call解决
  • 没有 obj 传入的时候 直接调用 callback
  • 根据 callback的返回值 ,如果为false 直接返回false 并阻断流程
  • 如果循环结束 callback 返回值 依然为true 返回 true

2.6.3 自定义实现

Array.prototype.myEvery = function (callback, obj) {
  if(!callback) throw (`${callback} is not a function`)
  for (let i = 0; i < this.length; i++) {
    if(obj){
      if(!callback.call(obj, this[i], i, this)) return false
    } else {
      if (!callback(this[i], i, this)) return false
    } 
  }
  return true
}

2.6.4 测试

let arr = [1, 3, 4]
let obj = {
  name: 1
}
let arr1 = []


console.log('--------传入function 官方-->自定义-----------')
console.log('官方----->', arr.every((value, index) => {
  return value >= 1
}))
console.log('自定义----->', arr.myEvery((value, index) => {
  return value >= 1
}))

console.log('--------传入function, obj 官方-->自定义-----------')
console.log('官方----->', arr.every(function (value, index){
  return value >= this.name
}, obj))
console.log('自定义----->', arr.myEvery(function (value, index){
  return value >= this.name
}, obj))

console.log('--------数组为空 官方-->自定义-----------')
console.log('官方----->', arr1.every(() => {
  return 1
}))
console.log('自定义----->', arr1.myEvery(() => {
  return 1
}))

console.log('-------不传function 官方-->自定义-----------')
console.log('官方----->', arr.every())
console.log('自定义----->', arr.myEvery())

2.7 findIndex()

2.7.1 功能概述

自定义方法名: myFindIndex()
功能: 检测返回数组中满足条件的第一个元素位置
参数: function() 必须
参数: obj 非必须
返回值: true false
是否改变原数组:
注意: 当需要传入obj的时候,方法必须是匿名函数,不能是箭头函数,因为箭头函数没有this

2.7.2 实现思路

  • function 不传 抛出错误
  • 当数组为空时,直接返回 -1
  • 当传入 obj时 ,需要改变 this的指向,也就是调用callback的是obj不再是 window使用call解决
  • 没有 obj 传入的时候 直接调用 callback
  • 根据 callback的返回值 ,如果为true 直接返回当前 下标 并阻断流程
  • 如果循环结束 callback 返回值 依然为false 返回 -1

2.7.3 自定义实现

Array.prototype.myFindIndex = function (callback, obj) {
  if(this.length === 0) return -1
  if(!callback) throw (`${callback} is not a function`)
  for (let i = 0; i < this.length; i++) {
    if(obj){
      if(callback.call(obj, this[i], i, this)) return i
    } else {
      if (callback(this[i], i, this)) return i
    } 
  }
  return -1
} 

2.7.4 测试

console.log('--------传入function 官方-->自定义-----------')
console.log('官方----->', arr.findIndex((value, index) => {
  return value > 1
}))
console.log('自定义----->', arr.myFindIndex((value, index) => {
  return value > 1
}))

console.log('--------传入function, obj 官方-->自定义-----------')
console.log('官方----->', arr.findIndex(function (value, index){
  return value < this.name
}, obj))
console.log('自定义----->', arr.myFindIndex(function (value, index){
  return value < this.name
}, obj))

console.log('--------数组为空 官方-->自定义-----------')
console.log('官方----->', arr1.findIndex(() => {
  return 1
}))
console.log('自定义----->', arr1.myFindIndex(() => {
  return 1
}))

console.log('-------不传function 官方-->自定义-----------')
console.log('官方----->', arr.findIndex())
console.log('自定义----->', arr.myFindIndex())

2.8 find()

2.8.1 功能概述

自定义方法名: myFind()
功能: 检测返回数组中满足条件的第一个元素
参数: function() 必须
参数: obj 非必须
返回值: 元素值 undefined
是否改变原数组:
注意: 当需要传入obj的时候,方法必须是匿名函数,不能是箭头函数,因为箭头函数没有this

2.8.2 实现思路

  • function 不传 抛出错误
  • 当数组为空时,直接返回 undefind
  • 当传入 obj时 ,需要改变 this的指向,也就是调用callback的是obj不再是 window使用call解决
  • 没有 obj 传入的时候 直接调用 callback
  • 根据 callback的返回值 ,如果为true 直接返回当前 元素值 并阻断流程
  • 如果循环结束 callback 返回值 依然为false 返回 undefined

2.8.3 自定义实现

Array.prototype.myFind = function (callback, obj) {
  if(this.length === 0) return undefined
  if(!callback) throw (`${callback} is not a function`)
  for (let i = 0; i < this.length; i++) {
    if(obj){
      if(callback.call(obj, this[i], i, this)) return this[i]
    } else {
      if (callback(this[i], i, this)) return this[i]
    } 
  }
  return undefined
} 

2.8.4 测试

console.log('--------传入function 官方-->自定义-----------')
console.log('官方----->', arr.find((value, index) => {
  return value > 1
}))
console.log('自定义----->', arr.myFind((value, index) => {
  return value > 1
}))

console.log('--------传入function, obj 官方-->自定义-----------')
console.log('官方----->', arr.find(function (value, index){
  return value < this.name
}, obj))
console.log('自定义----->', arr.myFind(function (value, index){
  return value < this.name
}, obj))

console.log('--------数组为空 官方-->自定义-----------')
console.log('官方----->', arr1.find(() => {
  return 1
}))
console.log('自定义----->', arr1.myFind(() => {
  return 1
}))

console.log('-------不传function 官方-->自定义-----------')
console.log('官方----->', arr.find())
console.log('自定义----->', arr.myFind())

2.9 map()

2.9.1 功能概述

自定义方法名: myMap()
功能: 返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值
参数: function() 必须
参数: obj 非必须
返回值: 处理后的新数组
是否改变原数组:
注意: 当需要传入obj的时候,方法必须是匿名函数,不能是箭头函数,因为箭头函数没有this

2.9.2 实现思路

  • function 不传 抛出错误
  • 当数组为空时,直接返回 []
  • 声明一个新数组 为 [] 供保存返回处理值 使用
  • 当传入 obj时 ,需要改变 this的指向,也就是调用callback的是obj不再是 window使用call解决
  • 没有 obj 传入的时候 直接调用 callback
  • 将callback的返回值保存到新数组
  • 如循环结束 返回新数组

2.9.3 自定义实现

Array.prototype.myMap = function (callback, obj) {
  let result = []
  if(!callback) throw (`${callback} is not a function`)
  for (let i = 0; i < this.length; i++) {
    if(obj){
      result[result.length] = callback.call(obj, this[i], i, this)
    } else {
      result[result.length] = callback(this[i], i, this)
    } 
  }
  return result
} 

2.9.4 测试

let arr = [4, 9, 16, 25];
let obj = {
  name: 10
}
let arr1 = []


console.log('--------传入function 官方-->自定义-----------')
console.log('官方----->', arr.map((value, index) => {
  return value > 1
}))
console.log('自定义----->', arr.myMap((value, index) => {
  return value > 1
}))

console.log('--------传入function, obj 官方-->自定义-----------')
console.log('官方----->', arr.map(function (value, index){
  return value < this.name
}, obj))
console.log('自定义----->', arr.myMap(function (value, index){
  return value < this.name
}, obj))

console.log('--------数组为空 官方-->自定义-----------')
console.log('官方----->', arr1.map(() => {
  return 1
}))
console.log('自定义----->', arr1.myMap(() => {
  return 1
}))

console.log('-------不传function 官方-->自定义-----------')
console.log('官方----->', arr.map())
console.log('自定义----->', arr.myMap())

2.10 filter()

2.10.1 功能概述

自定义方法名: myFilter()
功能: 返回一个新数组,数组中的元素为原始数组元素中满足回调条件的元素
参数: function() 必须
参数: obj 非必须
返回值: 处理后的新数组
是否改变原数组:
注意: 当需要传入obj的时候,方法必须是匿名函数,不能是箭头函数,因为箭头函数没有this

2.10.2 实现思路

  • function 不传 抛出错误
  • 当数组为空时,直接返回 []
  • 声明一个新数组 为 [] 供保存返回处理值 使用
  • 当传入 obj时 ,需要改变 this的指向,也就是调用callback的是obj不再是 window使用call解决
  • 没有 obj 传入的时候 直接调用 callback
  • 根据 callback的返回值 如果为 true 将 元素值 保存到新数组,如果为 false 不做处理
  • 如循环结束 返回新数组

2.10.3 自定义实现

Array.prototype.myFilter = function (callback, obj) {
  let result = []
  if(!callback) throw (`${callback} is not a function`)
  for (let i = 0; i < this.length; i++) {
    if(obj){
      if(callback.call(obj, this[i], i, this)) result[result.length] = this[i]
    } else {
      if (callback(this[i], i, this)) result[result.length] = this[i]
    } 
  }
  return result
} 

2.10.4 测试

let arr = [4, 9, 16, 25];
let obj = {
  name: 10
}
let arr1 = []


console.log('--------传入function 官方-->自定义-----------')
console.log('官方----->', arr.filter((value, index) => {
  return value > 5
}))
console.log('自定义----->', arr.myFilter((value, index) => {
  return value > 5
}))

console.log('--------传入function, obj 官方-->自定义-----------')
console.log('官方----->', arr.filter(function (value, index){
  return value < this.name
}, obj))
console.log('自定义----->', arr.myFilter(function (value, index){
  return value < this.name
}, obj))

console.log('--------数组为空 官方-->自定义-----------')
console.log('官方----->', arr1.filter(() => {
  return 1
}))
console.log('自定义----->', arr1.myFilter(() => {
  return 1
}))

console.log('-------不传function 官方-->自定义-----------')
console.log('官方----->', arr.filter())
console.log('自定义----->', arr.myFilter())

2.11 forEach()

2.11.1 功能概述

自定义方法名: myForEach()
功能: 调用数组的每个元素,并将元素传递给回调函数
参数: function() 必须
参数: obj 非必须
返回值:
是否改变原数组: 可能会被 callback改变
注意: 当需要传入obj的时候,方法必须是匿名函数,不能是箭头函数,因为箭头函数没有this

2.11.2 实现思路

  • function 不传 抛出错误
  • 没有返回值
  • 将元素值、元素下标、数组传给callback即可

2.11.3 自定义实现

Array.prototype.myForEach = function (callback, obj) {
  if(!callback) throw (`${callback} is not a function`)
  for (let i = 0; i < this.length; i++) {
    if(obj)callback.call(obj, this[i], i, this)
    else callback(this[i], i, this)
  }
} 

2.11.4 测试

let arr = [4, 9, 16, 25];

let arr1 = []


console.log('--------传入function 官方-->自定义-----------')
console.log('官方----->', arr.forEach((value, index) => {
  console.log(value)
}))
console.log('自定义----->', arr.myForEach((value, index) => {
  console.log(value)
}))

console.log('--------数组为空 官方-->自定义-----------')
console.log('官方----->', arr1.forEach(() => {
  return 1
}))
console.log('自定义----->', arr1.myForEach(() => {
  return 1
}))

console.log('-------不传function 官方-->自定义-----------')
console.log('官方----->', arr.forEach())
console.log('自定义----->', arr.myForEach())

2.12 reduce()

2.12.1 功能概述

自定义方法名: myReduce()
功能: 接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值
参数: function() 必须
参数: initVal 非必须
返回值: 最后累加的值
是否改变原数组:

2.12.2 实现思路

  • function 不传 抛出错误
  • 数组为空,initVal为undefined 给出报错
  • initVal为undefined 循环是判断 数组的第一个值类型是否为number是则 result为0 否则 result为 ‘’
  • 如果initVal有值则直接传入回调
  • 返回累加的值

2.12.3 自定义实现

Array.prototype.myReduce = function (callback, initVal) {
  if (!callback) throw callback + 'is not a function'
  if (this.length === 0) {
    if(typeof initVal === 'undefined') throw 'Reduce of empty array with no initial value'
  }
  let result = initVal
  for (let i = 0; i < this.length; i++) {
    if(typeof result === 'undefined') {
      if(typeof this[0] === 'number') result = callback(0, this[i], i, this)
      else result = callback('', this[i], i, this)
    }
    else result = callback(result, this[i], i, this)
  }
  return result
} 

2.12.4 测试

let arr2 = ['aaa' ,4, 9, 16, 25];
let arr = [4, 9, 16, 25];

let arr1 = []


console.log('--------传入function initVal为undefined 官方-->自定义-----------')
console.log('官方----->', arr.reduce((total,value, index) => {
  return total + value
}))
console.log('自定义----->', arr.myReduce((total,value, index) => {
  return total + value
}))

console.log('--------传入function initVal为 "" 官方-->自定义-----------')
console.log('官方----->', arr.reduce((total,value, index) => {
  return total + value
}, ''))
console.log('自定义----->', arr.myReduce((total,value, index) => {
  return total + value
}, ''))

console.log('--------传入function initVal为 undefined 数组含有字符串 官方-->自定义-----------')
console.log('官方----->', arr2.reduce((total,value, index) => {
  return total + value
}))
console.log('自定义----->', arr2.myReduce((total,value, index) => {
  return total + value
}))

console.log('--------数组为空 且 initVal 为 ‘’官方-->自定义-----------')
console.log('官方----->', arr1.reduce(() => {
  return 1
}, ''))
console.log('自定义----->', arr1.myReduce(() => {
  return 1
}, ''))

console.log('--------数组为空 且 initVal 为undefined 官方-->自定义-----------')
console.log('官方----->', arr1.reduce(() => {
  return 1
}))
console.log('自定义----->', arr1.myReduce(() => {
  return 1
}))
console.log('-------不传function 官方-->自定义-----------')
console.log('官方----->', arr.reduce())
console.log('自定义----->', arr.myReduce())

三、小结

这期总结了12个数组的方法,并不是很完善的实现了官方方法的所有功能,比如对空位数组的适配就没有做,还有许多不常见的场景,这里我考虑的不是很完善。写了这么多呢,主要也是希望大家能够对这些方法的使用有一个更深的认识,在工作中也更容易抉择。虽然还有几个方法没写,那几个使用的比较少,大家有兴趣可以实现一下,如果有什么不懂的也欢迎大家留言讨论。数组专题在此也就要告一段落了,阿树仍有许多不足,希望大家不吝赐教!下一期,阿树暂时还不确定整理哪一部分,仅仅是基础,对大家的帮助可能也不是很大,所以大家有什么想了解的方向,可以留言,阿树一定积极准备!我是阿树,我们下期见!

四、声明

  • 创作不易,转载请注明来源
  • 创作不易,copy请远离

五、参考文献

菜鸟教程