JavaScript-实现数组方法-遍历方法forEach map

68 阅读3分钟

实现forEach

forEach

参数

  • 回调函数callbackFn(当前元素element,索引index,array调用forEach()的数组本身)回调函数

回调函数的参数是按顺序传入的 如果只传入索引需要占位符顺序传入参数

  • this.Arg指定回调函数的this指向 箭头函数没有this'

没有返回值

返回undefined 不能继续链式调用(map区别)

  • 图上是指 在回调函数有返回值的情况下 forEach方法也是没有返回值的没有返回值
  • 回调函数是箭头函数的情况下 箭头函数后面的表达式会被自动作为返回值箭头函数

不更改原数组

不更改原数组

基于原数组长度遍历

基于初始长度

稀疏数组的空槽不执行回调函数

这里稀疏数组是指数组可以包含“空槽”,这与用值 undefined 填充的槽不一样

槽的行为就像填入了undefined一样在这里插入图片描述 判断是否遍历到空槽目前先用undefined来判断 但是有undefined元素的数组也不会执行回调函数 这个判断方式不够严谨 等我学到更合适的方法再进行分享

创建方式和不执行回调函数如下图所示 空属性不执行回调函数

实现

  • 首先把原数组的长度保存
  • 然后考虑thisArg参数 利用||运算符 没传入的情况就指向全局window
  • 然后遍历数组 如果这个元素不是undefinedcall方法执行参数顺序为(this指向 元素的值 索引 和传入数组)
  Array.prototype.myForeach = function (callback, thisArg) {
      //基于原数组长度
      let len = this.length
      thisArg = thisArg || window
      for (let i = 0; i < len; i++) {
        if (this[i] !== undefined) {
          callback.call(thisArg, this[i], i, this)
        }
      }
    }
  • 以下是测试用例
	//回调函数参数顺序
	arr.myForeach((_, index) => console.log(`index 	${index}`))
    arr.myForeach(() => {
      console.log('遍历');
    })
    arr.myForeach((value) => console.log('value', value))
    let num = {
      count: 0
    }
    //thisArg参数
    arr.myForeach(function () {
      this.count++
    }, num)
    console.log(num.count);  //5
	//基于原数组操作
    arr.myForeach((item, index) => {
      console.log(item);//打印原数组
      arr.push(index + 5)
    })
    console.log('不改变原数组', arr,);
    //此时原数组改变[1, 2, 3, 4, 2, 5, 6, 7, 8, 9]
	//稀疏数组的情况
    const arr1 = [1, 2]
    arr1[5] = 5
    arr1.myForeach((item) => {
      console.log(item);  //只打印有值的元素

    })

实现map

map

参数

forEach()一样

  • 回调函数callbackFn(正在处理的元素element,索引index,调用的数组本身array
  • thisArg执行回调函数this的值

注意 有thisArg参数的时候不能用箭头函数当作回调函数箭头函数this

返回新数组

map方法返回新数组 这是和forEach的区别 返回新数组

forEach没有返回值

稀疏数组的空槽不执行回调函数

这里也和forEach一样 稀疏数组

稀疏数组调用filter forEachmap 方法都不执行回调函数

基于原数组长度

基于第一次遍历的数组长度

注意这里的undefined是五个控制台打印表达式的返回值 控制台> 注意写对象的属性名![[Pasted image 20251106172757.png]]

基于原数组长度

实现

这里和forEach的区别是创建newArr新数组存放map的返回值

不用push方法是为了防止稀疏数组情况下索引混乱稀疏数组索引混乱

  //map()
    Array.prototype.myMap = function (callback, thisArg) {
      thisArg = thisArg || window
      let len = this.length
      let newArr = []
      for (let i = 0; i < len; i++) {
        if (this[i] !== undefined) {
          newArr[i] = callback.call(thisArg, this[i], i, this)
        }
      }
      return newArr
    }

  • 以下是测试用例
  const mapArr = [1, 2, 3]
    //返回新数组
    // mapArr.myMap((value) => value + 1)  // [2, 3, 4]
    //空属性不执行回调函数
    mapArr[5] = 5
    mapArr.myMap((value) => value + 1)  //[2, 3, 4, 空属性 × 2, 6]
    //thisArg参数
    let mapArr1 = [1, 2, 3]
    let numMap = {
      count: 0
    }
    //注意箭头函数的this指向外层作用域的this
    mapArr1.myMap(function () {
      this.count++
      console.log(this);
    }, numMap)
    console.log(numMap);//{count: 3}