手写 javascript ES6 数组新增的迭代器,加深理解和巩固。

手写 js es6 数组新增的迭代器,加深理解和巩固。

背景:在使用 es6 数组提供的 find,some,filter…等迭代器,原理上都是 es5 普通 for 循环的一种通用场景的实现的语法糖。这里手写简单实现,来加深巩固,供大家参考指正。

迭代器描述参考【mdn 官方文档】

数据示例

//下面所写方法使用数据均参考下面list定义

let arr = [
  {
    id: 1,
    name: "小明",
    age: 18,
    site: "https://blog.csdn.net/pangGeee?type=blog",
  },
  {
    id: 2,
    name: "小红",
    age: 22,
    site: "https://blog.csdn.net/pangGeee?type=blog",
  },
  {
    id: 3,
    name: "小力",
    age: 25,
    site: "https://blog.csdn.net/pangGeee?type=blog",
  },
  {
    id: 4,
    name: "小吖",
    age: 33,
    site: "https://blog.csdn.net/pangGeee?type=blog",
  },
  {
    id: 5,
    name: "小范",
    age: 18,
    site: "https://blog.csdn.net/pangGeee?type=blog",
  },
  {
    id: 6,
    name: "小平",
    age: 20,
    site: "https://blog.csdn.net/pangGeee?type=blog",
  },
  {
    id: 7,
    name: "小北",
    age: 18,
    site: "https://blog.csdn.net/pangGeee?type=blog",
  },
  {
    id: 8,
    name: "小法",
    age: 16,
    site: "https://blog.csdn.net/pangGeee?type=blog",
  },
];

数组:手写 forEach

forEach() 方法是一个迭代方法。它按索引升序地为数组中的每个元素调用一次提供的 callbackFn 函数。与 map() 不同,forEach() 总是返回 undefined,而且不能继续链式调用。其典型的用法是在链式调用的末尾执行某些操作。

Array.prototype.pangGeForEach = function (callbackFn) {
  for (let i = 0; i < this.length; i++) {
    // 检查数组是否包含当前索引
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入当前元素、当前索引和原数组
      callbackFn(this[i], i, this);
    }
  }
};

// 示例用法
arr.pangGeForEach((item, index, arr) => {
  console.log(item, index, arr);
});

数组:手写 fliter

filter() 方法是一个迭代方法。它为数组中的每个元素调用提供的 callbackFn 函数一次,并构造一个由所有返回真值的元素值组成的新数组。未通过 callbackFn 测试的数组元素不会包含在新数组中。

Array.prototype.pangGeFilter = function (callbackFn) {
  const newArr = [];
  const length = this.length;
  for (let i = 0; i < length; i++) {
    // 检查数组是否包含当前索引
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入当前元素、当前索引和原数组
      if (callbackFn(this[i], i, this)) {
        // 如果回调函数返回 true,则将当前元素添加到新数组中
        newArr.push(this[i]);
      }
    }
  }

  // 返回新数组,其中包含满足条件的元素
  return newArr;
};

// 示例用法
let newArr = arr.pangGeFilter((item, index, arr) => {
  console.log(item, index, arr, "每行打印");
  return item.age === 18;
});
console.log(newArr, "结果");

数组:手写 map

map() 方法是一个迭代方法。它为数组中的每个元素调用一次提供的 callbackFn 函数,并用结果构建一个新数组。

Array.prototype.pangGeMap = function (callbackFn) {
  const newArr = [];

  for (let i = 0; i < this.length; i++) {
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入当前元素、当前索引和原数组
      const mappedValue = callbackFn(this[i], i, this);
      // 将映射后的结果添加到新数组中
      newArr.push(mappedValue);
    }
  }
  return newArr;
};

// 示例用法
let newArr = arr.pangGeMap((item, index, arr) => {
  console.log(item, index, arr, "每行打印");
  return {
    ...item,
    gender: item.age === 18 ? "女" : "男",
  };
});
console.log(newArr, "结果");

数组:手写 find

find() 方法是一个迭代方法。它按索引升序顺序为数组中的每个元素调用提供的 callbackFn 函数,直到 callbackFn 返回一个真值。然后 find() 返回该元素并停止迭代数组。如果 callbackFn 从未返回真值,则 find() 返回 undefined。

Array.prototype.pangGeFind = function (callbackFn) {
  for (let i = 0; i < this.length; i++) {
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入当前元素、当前索引和原数组
      if (callbackFn(this[i], i, this)) {
        // 如果回调函数返回 true,则返回当前元素
        return this[i];
      }
    }
  }
  return undefined;
};

// 示例用法
let newArr = arr.pangGeFind((item, index, arr) => {
  console.log(item, index, arr, "每行打印");
  return item.name === "小红";
});
console.log(newArr, "结果");

Alt

数组:手写 findLast

findLast() 是一个迭代方法。该方法对数组每一个元素按降序(索引从大到小)执行 callbackFn 函数,直到 callbackFn 返回一个真值。然后 findLast() 返回该元素的值并停止遍历数组。如果 callbackFn 没有返回一个真值,则 findLast() 返回 undefined。

Array.prototype.pangGeFindLast = function (callbackFn) {
  const length = this.length;

  for (let i = length - 1; i >= 0; i--) {
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入当前元素、当前索引和原数组
      if (callbackFn(this[i], i, this)) {
        // 如果回调函数返回 true,则返回当前元素
        return this[i];
      }
    }
  }

  return undefined;
};

// 示例用法
let newArr = arr.pangGeFindLast((item, index, arr) => {
  console.log(item, index, arr, "每行打印");
  return item.name === "小北";
});
console.log(newArr, "结果");

结果图片描述

数组:手写 findIndex

findIndex() 是一种迭代方法。它按照索引升序依次遍历数组中的每个元素,并调用提供的 callbackFn 函数,直到 callbackFn 返回一个真值。然后 findIndex() 返回该元素的索引并停止遍历数组。如果 callbackFn 从未返回一个真值,则 findIndex() 返回 -1。

Array.prototype.pangGeFindIndex = function (callbackFn) {
  const length = this.length;

  for (let i = 0; i < length; i++) {
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入当前元素、当前索引和原数组
      if (callbackFn(this[i], i, this)) {
        // 如果回调函数返回 true,则返回当前索引
        return i;
      }
    }
  }
  // 如果没有找到符合条件的元素,则返回 -1
  return -1;
};

// 示例用法
let newArr = arr.pangGeFindIndex((item, index, arr) => {
  console.log(item, index, arr, "每行打印");
  return item.name === "小北";
});
console.log(newArr, "结果");

结果图片描述

数组:手写 findLastIndex

findLastIndex() 方法是一个迭代方法。它为数组中的每个元素按索引降序调用一次提供的 callbackFn 函数,直到 callbackFn 返回一个真值。然后 findLastIndex() 返回元素的索引并且停止遍历数组。如果 callbackFn 没有返回一个真值,则 findLastIndex() 返回 -1。

Array.prototype.pangGeFindLastIndex = function (callbackFn) {
  const length = this.length;

  for (let i = length - 1; i >= 0; i--) {
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入当前元素、当前索引和原数组
      if (callbackFn(this[i], i, this)) {
        // 如果回调函数返回 true,则返回当前索引
        return i;
      }
    }
  }
  // 如果没有找到符合条件的元素,则返回 -1
  return -1;
};

// 示例用法
let newArr = arr.pangGeFindLastIndex((item, index, arr) => {
  console.log(item, index, arr, "每行打印");
  return item.name === "小北";
});
console.log(newArr, "结果");

数组:手写 some

some() 方法是一个迭代方法。它为数组中的每个元素调用一次指定的 callbackFn 函数,直到 callbackFn 返回一个真值。如果找到这样的元素,some() 方法将会立即返回 true 并停止遍历数组。否则,如果 callbackFn 对所有元素都返回假值,some() 就会返回 false。

Array.prototype.pangGeSome = function (callbackFn) {
  const length = this.length;
  for (let i = 0; i < length; i++) {
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入当前元素、当前索引和原数组
      if (callbackFn(this[i], i, this)) {
        // 如果回调函数返回 true,则返回 true
        return true;
      }
    }
  }
  // 如果没有找到符合条件的元素,则返回 false
  return false;
};

// 示例用法
let newArr = arr.pangGeSome((item, index, arr) => {
  console.log(item, index, arr, "每行打印");
  return item.name.indexOf("红") > -1;
});
console.log(newArr, "结果");

在这里插入图片描述

数组:手写 every

every() 方法是一个迭代方法。它为数组中的每个元素调用一次指定的 callbackFn 函数,直到 callbackFn 返回一个假值。如果找到这样的元素,every() 方法将会立即返回 false 并停止遍历数组。否则,如果 callbackFn 为每个元素返回一个真值,every() 就会返回 true。

Array.prototype.pangGeEvery = function (callbackFn) {
  const length = this.length;

  for (let i = 0; i < length; i++) {
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入当前元素、当前索引和原数组
      if (!callbackFn(this[i], i, this)) {
        // 如果回调函数返回 false,则返回 false
        return false;
      }
    }
  }

  // 如果所有元素都满足条件,则返回 true
  return true;
};

// 示例用法
let newArr = arr.pangGeEvery((item, index, arr) => {
  console.log(item, index, arr, "每行打印");
  return item.name.indexOf("pangGe") > -1;
});
console.log(newArr, "结果");

在这里插入图片描述

数组:手写 reduce

reduce() 方法是一个迭代方法。它按升序对数组中的所有元素运行一个“reducer”回调函数,并将它们累积到一个单一的值中。每次调用时,callbackFn 的返回值都作为 accumulator 参数传递到下一次调用中。accumulator 的最终值(也就是在数组的最后一次迭代中从 callbackFn 返回的值)将作为 reduce() 的返回值。

Array.prototype.pangGeReduce = function (callbackFn, initialValue) {
  const length = this.length;

  // 如果初始值未提供,则使用数组的第一个元素作为初始值,并将索引设置为 1
  let accumulator = initialValue === undefined ? this[0] : initialValue;
  let startIndex = initialValue === undefined ? 1 : 0;

  for (let i = startIndex; i < length; i++) {
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入累加器、当前元素、当前索引和原数组
      accumulator = callbackFn(accumulator, this[i], i, this);
    }
  }

  // 返回最终的累加值
  return accumulator;
};
// 示例用法,计算年龄总和
let sumAge = arr.pangGeReduce((acc, cur, index, arr) => {
  console.log(acc, cur, index, arr, "每行打印");
  acc += cur.age;
  return acc;
}, 0);
console.log(sumAge, "结果");

在这里插入图片描述

数组:手写 reduceRight

reduceRight() 方法是一个迭代方法。它为数组中的所有元素降序调用“reducer”回调函数,并将它们累积到一个单一的值中。

Array.prototype.pangGeReduceRight = function (callbackFn, initialValue) {
  const length = this.length;

  // 如果初始值未提供,则使用数组的最后一个元素作为初始值,并将索引设置为 length - 2
  let accumulator =
    initialValue === undefined ? this[length - 1] : initialValue;
  let startIndex = initialValue === undefined ? length - 2 : length - 1;

  // 遍历数组的每个元素,从右到左
  for (let i = startIndex; i >= 0; i--) {
    if (this.hasOwnProperty(i)) {
      // 调用回调函数,传入累加器、当前元素、当前索引和原数组
      accumulator = callbackFn(accumulator, this[i], i, this);
    }
  }

  // 返回最终的累加值
  return accumulator;
};

// 示例用法,计算id总和
let sumId = arr.pangGeReduceRight((acc, cur, index, arr) => {
  console.log(acc, cur, index, arr, "每行打印");
  acc += cur.id;
  return acc;
}, 0);
console.log(sumId, "结果");

在这里插入图片描述

总结:

上述代码中

  • 只是和 es6 中实现结果相同,相比 es6 源码少了严谨性,少了很多边界判断,仅供参考和理解。
  • 在过完所有自定义的迭代方法后,是不是更加明了,在每个语法糖实现的背后,存在的都是大道至简。

有疑问的同学可以私信我、对帮助到同学欢迎大家收藏评论。

  • 19
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值