数组
1.some /every 伪装可控遍历
- 场景:需要遍历 + 中途终止,不想写 for 循环
- 对比:every 是 return false 停止
1)some 遍历终止(return true 停止)
[1, 2, 3, 4].some((v) => {
console.log(v);
return v === 3;
});
- every 遍历终止(return false 停止)
-
场景:需要遍历 + 中途终止,不想写 for 循环
-
对比:every 是 return false 停止
[1, 2, 3, 4].every((v) => { console.log(v); return v !== 3; });
2.reduce 一次遍历:过滤 + 映射 + 统计
前言:我是基础忘了 补些基础
// arr.reduce((累加器, 当前项, 索引, 原数组) => {
// return 新的累加值
// }, 初始值)
注明: 初始值写 0 / [] / {},完全看你最后想要得到什么类型的数据
-
想要数字 → 初始值用 0
-
想要数组 → 初始值用 []
-
想要对象 → 初始值用 {}
应用的小场景:
1)求和: acc:累加器,上一次返回的结果cur:当前遍历的元素0:初始值(必须写,防止空数组报错)
const arr = [1, 2, 3, 4];
const sum = arr.reduce((acc, cur) => {
return acc + cur;
}, 0);
console.log(sum); // 10
2)数组去重
const arr1 = [1, 2, 3, 4, 3];
const sum1 = arr1.reduce((acc, cur) => {
if (!acc.includes(cur)) acc.push(cur);
return acc;
}, []);
console.log(sum1);
在重点补充下:
1.初始值是0 :最后的是数字(求和、累计)
// 案例
const arry = [1, 2, 3];
// acc 一开始是数字 0 一直和数字相加
const sun = arry.reduce((acc, cur) => {
return acc + cur;
}, 0);
console.log(sun, "测试结果", "场景:求和、计数、累加");
2.初始值是[]:最后的结果是数据(过滤、去重、收集 )
//2.初始值是[]:最后的结果是数据(过滤、去重、收集 )
const y = [1, 2, 3];
// acc 一开始是空数组,往里面 push 元素
const ysesult = y.reduce((acc, cur) => {
acc.push(cur * 2);
return acc;
}, []);
console.log(ysesult, "场景:过滤、映射、去重、收集元素");
-
初始值是 {}:最后结果是 对象(分组、统计、键值对)
const str = "aabcc";
// acc 一开始是空对象,给对象加属性
// ['a', 'a', 'b', 'c', 'c']
const obj = str.split("").reduce((acc, cur) => {
acc[cur] = (acc[cur] || 0) + 1;
return acc;
}, {});
console.log(obj, "场景:统计次数、分组、转对象");
//具体:
// acc[cur]
// cur 是当前字母,比如 a
// acc[a] → 取对象里 a 的次数
// acc[cur] || 0
// 如果 a 还没出现过 → acc[a] 是 undefined
// undefined || 0 → 变成 0
// +1
// 出现一次就 +1
// 第四步:逐字运行一遍(你马上懂)
// 数组:['a','a','b','c','c']初始 acc:{}
// 第 1 个字符 a
// acc [a] 不存在 → 0+1 → a:1acc 变成 {a:1}
// 第 2 个字符 a
// acc[a] =1 →1+1 → a:2acc 变成 {a:2}
// 第 3 个字符 b
// acc [b] 不存在 →0+1 → b:1acc 变成 {a:2,b:1}
// 第 4 个字符 c
// acc [c] 不存在 →0+1 → c:1
// 第 5 个字符 c
// acc[c]=1 →1+1 → c:2
// 这个字符出现过就 + 1,没出现过就从 0 开始 + 1
// 不简写
//const str = 'aabcc'
// 转成数组:['a','a','b','c','c']
// const arr = str.split('')
// const obj = arr.reduce(function(acc, cur) {
// // 1. 先判断这个字符之前有没有统计过
// if (acc[cur] === undefined) {
// // 没出现过,初始次数 = 1
// acc[cur] = 1
// } else {
// // 出现过,次数 +1
// acc[cur] = acc[cur] + 1
// }
// // 把更新后的对象返回给下一次循环
// return acc
// }, {}) // 一开始 acc = 空对象 {}// console.log(obj) // {a:2, b:1, c:2}
最终场景: reduce 一次遍历:过滤 + 映射 + 统计
const goods = [
{ name: "a", price: 80 },
{ name: "b", price: 150 },
{ name: "c", price: 200 },
];
// 需求:过滤价格 > 100,价格 ×2,同时算总价
const price = goods.reduce(
(acc, cur) => {
if (cur.price > 100) {
acc.list.push(cur.name);
acc.sum += cur.price * 2;
}
return acc;
},
{ list: [], sum: 0 },
);
console.log(price);
// 场景:大数据列表,减少多次遍历,提升性能
-
forEach+try/catch 强制中断
const arr = [1, 2, 3, 4, 5];
try {
arr.forEach(item => {
if (item === 3) throw "停止遍历";
console.log(item); // 输出 1 2
});
} catch (e) {}
- 场景:老项目必须用 forEach 又要终止,不推荐业务用
- 缺点:抛异常、可读性差
- 迭代器 Symbol.iterator/ 递归遍历
场景:手写框架、树形结构、深层扁平化
const arr = [1, 2, 3];
const it = arr[Symbol.iterator]();
let result;
while (!(result = it.next()).done) {
console.log(result.value); // 1 2 3
}
字符串
-
基础遍历:for /for...of 场景:字符逐个校验、遍历中文 / 特殊字符
const strq = "hello";
for (let i = 0; i < strq.length; i++) {
console.log(i, "i");
}
for (const s of strq) {
console.log(s, "s");
}
2.split + 数组方法(字符串变态处理核心)
场景 1:过滤掉空格、特殊字符
// 字符串本身没有 map/filter,必须转数组再操作
// 场景 1:过滤掉空格、特殊字符
const str1 = "a b c 123";
const res = str1
.split("")
.filter((s) => s !== " ")
.join("");
console.log(res, "res");
场景2:字符转大写 / 小写、批量替换
console.log("---场景 2:字符转大写 / 小写、批量替换---");
const str2 = "hello";
const upperStr = str2
.split(" ")
.map((s) => s.toLocaleUpperCase())
.join("");
3.reduce 处理字符串(变态高频)
场景:统计字符出现次数
const more = "abacaba";
const count = more.split("").reduce((acc, cur) => {
acc[cur] = (acc[cur] || 0) + 1;
return acc;
}, {});
console.log(count, "count");
进阶版: 找出次数最多的字符:
const test = "aabccddeeeee";
const testres = test.split("").reduce(
(acc, cur) => {
acc[cur] = (acc[cur] || 0) + 1;
if (acc[cur] > acc.maxNum) {
acc.maxNum = acc[cur];
acc.maxChar = cur;
}
return acc;
},
{ maxNum: 0, maxChar: "" },
);
// 完整
const strlong = "aabccddeeeee";
// 1. 统计每个字符次数
const countObj = strlong.split("").reduce((acc, cur) => {
if (acc[cur] === undefined) {
acc[cur] = 1;
} else {
acc[cur]++;
}
return acc;
}, {});
// 2. 找出次数最多的字符
let maxChar = "";
let maxNum = 0;
for (const key in countObj) {
if (countObj[key] > maxNum) {
maxNum = countObj[key];
maxChar = key;
}
}
console.log(countObj); // {a:2,b:1,c:2,d:2,e:5}
console.log("最多字符:", maxChar, "次数:", maxNum); // e 5
- some /every 用于字符串校验
场景:各种校验 正则
// 是否包含数字
const wy = "abc123".split("").some((s) => !isNaN(Number(s)));
console.log(wy, "是否包含数字");
// 是否包含字母
console.log(
"abc".split("").every((s) => /[a-z]/.test(s)),
"是否包含字母",
);
-
字符串迭代器(和数组通用)
const it = "test"[Symbol.iterator](); let r; while (!(r = it.next()).done) console.log(r.value);
小结:
数组、 字符串 场景:
数组:增删改查、批量处理、聚合统计、多操作合并用 reduce
字符串:先 split('') 转数组,再用数组所有高阶方法
变态组合核心:
中断遍历:some/every
一次遍历多操作:reduce
底层控制:迭代器
字符串处理:字符串 → 数组 → 数组方法 → join