这篇主要解决一个实际问题:当你面对对象、数组、字典和循环时,应该用哪种写法,为什么。
?? 和 || 的区别
?? 只在值为 null 或 undefined 时使用默认值。
const value = input ?? "default";|| 会在所有假值时使用默认值,包括 false、0、""、NaN、null、undefined。
const page = query.page || 1;如果 0 是合法值,不要用 || 做默认值。
const discount = userDiscount ?? 0;Record 字典
Record<K, V> 表示一个 key-value 映射。
const userAges: Record<string, number> = {
Alice: 25,
Bob: 30,
};如果 key 是固定集合,可以用联合类型限制。
type Role = "admin" | "editor" | "viewer";
const permissions: Record<Role, string[]> = {
admin: ["read", "write", "delete"],
editor: ["read", "write"],
viewer: ["read"],
};这比 Record<string, string[]> 更安全,因为少写一个 role 会直接报错。
索引签名
索引签名适合 key 完全动态的对象。
interface ScoreMap {
[name: string]: number;
}
const scores: ScoreMap = {};
scores.Alice = 95;缺点是它允许任意字符串 key,所以约束比联合类型弱。
循环怎么选
for 适合需要索引、需要提前退出、需要精细控制循环条件的场景。
for (let i = 0; i < items.length; i++) {
if (items[i] === target) break;
}for...of 适合遍历数组、字符串、Set 等可迭代对象,直接拿到值。
for (const fruit of fruits) {
console.log(fruit);
}for...in 适合遍历对象 key,但要注意原型链属性。
for (const key in person) {
if (Object.prototype.hasOwnProperty.call(person, key)) {
console.log(key, person[key as keyof typeof person]);
}
}forEach 与 map
forEach 用来执行副作用,不返回新数组。
numbers.forEach((num) => {
console.log(num);
});map 用来转换数组,并返回新数组。
const doubled = numbers.map((num) => num * 2);简单规则:
- 要生成新数组:用
map - 要过滤数组:用
filter - 要累计结果:用
reduce - 只是打印、调用函数、写日志:用
forEach - 需要
break或continue:用for...of或for