手写 js es6 数组新增的迭代器,加深理解和巩固。
背景:在使用 es6 数组提供的 find,some,filter…等迭代器,原理上都是 es5 普通 for 循环的一种通用场景的实现的语法糖。这里手写简单实现,来加深巩固,供大家参考指正。
文章目录
数据示例
//下面所写方法使用数据均参考下面list定义
let arr = [
{
id: 1,
name: "小明",
age: 18,
site: "https://blog.youkuaiyun.com/pangGeee?type=blog",
},
{
id: 2,
name: "小红",
age: 22,
site: "https://blog.youkuaiyun.com/pangGeee?type=blog",
},
{
id: 3,
name: "小力",
age: 25,
site: "https://blog.youkuaiyun.com/pangGeee?type=blog",
},
{
id: 4,
name: "小吖",
age: 33,
site: "https://blog.youkuaiyun.com/pangGeee?type=blog",
},
{
id: 5,
name: "小范",
age: 18,
site: "https://blog.youkuaiyun.com/pangGeee?type=blog",
},
{
id: 6,
name: "小平",
age: 20,
site: "https://blog.youkuaiyun.com/pangGeee?type=blog",
},
{
id: 7,
name: "小北",
age: 18,
site: "https://blog.youkuaiyun.com/pangGeee?type=blog",
},
{
id: 8,
name: "小法",
age: 16,
site: "https://blog.youkuaiyun.com/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, "结果");
数组:手写 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 源码少了严谨性,少了很多边界判断,仅供参考和理解。
- 在过完所有自定义的迭代方法后,是不是更加明了,在每个语法糖实现的背后,存在的都是大道至简。
有疑问的同学可以私信我、对帮助到同学欢迎大家收藏评论。