其他
编写、审查或重构 JavaScript…
适用于任何 JavaScript 项目的编码、代码审查、调试、重构、架构设计、性能优化与面试准备。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
编写、审查或重构 JavaScript 通用
解决思路
- 变量与作用域:默认使用 `const`;只在需要重新赋值时使用 `let`;避免使用 `var`。
- 变量与作用域:理解 `var` 是函数作用域、存在变量提升、可重复声明;`let`/`const` 是块级作用域、不可在同一作用域重复声明。
- 变量与作用域:`const` 必须初始化且引用不可重新赋值,但对象/数组内容仍可修改;不要把它当作深度不可变。
- 数据类型:记住 7 种原始类型:`String`、`Number`、`BigInt`、`Boolean`、`undefined`、`null`、`Symbol`;其余如数组、函数、日期等都是对象。
- 数据类型:用 `typeof` 检查类型;注意 `typeof null === 'object'` 是历史遗留问题;用 `Array.isArray()` 判断数组。
- 数据类型:判断 `null` 用 `value === null`;判断 `null` 或 `undefined` 用 `value == null`。
- 函数:函数是一等公民,可赋值给变量、作为参数传递、从其他函数返回。
- 函数:掌握函数声明、函数表达式、箭头函数;函数声明会提升,函数表达式不会。
- 函数:箭头函数没有自己的 `this`,不能用作构造函数,也没有 `arguments` 对象。
- 对象与数组:用对象字面量创建对象;用点号或中括号访问属性;用赋值增改属性;用 `delete` 删除属性。
- 数组:用 `map`/`filter`/`reduce` 做转换、过滤、聚合;用 `forEach` 迭代;用 `find`/`findIndex`/`includes` 查找。
- 数组:用 `push`/`pop`/`unshift`/`shift`/`splice` 修改原数组;用 `slice`/`concat`/展开运算符做非变异操作。
- 数组:记住 `reverse` 和 `sort` 会变异原数组;需要非变异排序时先复制再排序。
- 闭包:用闭包让函数访问外层词法作用域变量,即使外层函数已返回。
- 闭包:用闭包实现私有变量、工厂函数、事件处理器、回调保持状态、模块模式。
- 闭包:通过返回对象方法操作私有变量,例如 `createCounter` 返回 `increment`/`decrement`/`getCount`。
- 原型与继承:理解每个对象都有内部 `[[Prototype]]` 链接,JavaScript 使用原型继承。
- 原型与继承:用构造函数创建对象,把共享方法挂在 `Constructor.prototype` 上。
- 原型与继承:用 `Object.create(Parent.prototype)` 建立原型链,并修正 `Child.prototype.constructor = Child`。
- 原型与继承:在子构造函数中用 `Parent.call(this, ...)` 调用父构造函数。
- 类:用 `class` 语法糖定义构造函数、实例方法、`static` 方法、`extends` 继承、`super` 调用父类。
- 类:在子类中重写方法时可用 `super.method()` 扩展父类行为;用 `get`/`set` 定义访问器。
- 解构:用数组解构提取元素和剩余项;用对象解构提取属性;支持重命名、默认值、嵌套解构。
- 解构:在函数参数中直接解构对象,并为参数设置默认值,例如 `function greet({ name, age = 0 }) {}`。
- 展开与剩余:用展开运算符 `...` 展开数组、对象、函数参数;用剩余参数收集多个参数。
- 展开与剩余:用 `[...arr]` 或 `{ ...obj }` 做浅拷贝;注意不是深拷贝。
- 模板字面量:用反引号和 `${}` 做字符串插值、表达式计算、多行字符串。
- 模板字面量:用标签模板处理自定义字符串拼接,例如高亮函数。
- 可选链:用 `?.` 安全访问可能为 `null`/`undefined` 的嵌套属性、方法和数组元素,避免报错。
- 空值合并:用 `??` 只在 `null`/`undefined` 时给默认值;不要用 `||` 替代,因为 `0`、`''`、`false` 也会触发默认值。
- 模块:用命名导出 `export const`/`export function`/`export { }` 和默认导出 `export default`。
- 模块:用 `import { name } from './file.js'`、`import App from './App.js'`、`import * as Math from './math.js'`、`import './polyfills.js'`。
- 模块:导入时可重命名:`import { multiply as mult } from './math.js'`;可混合默认导入和命名导入。
- 事件循环:理解调用栈、Web APIs、回调队列、事件循环;微任务如 Promise 优先于宏任务如 setTimeout。
- 回调:用 error-first 回调处理异步结果;注意多层嵌套会导致回调地狱。
- Promise:用 `new Promise((resolve, reject) => {})` 创建 Promise;用 `then`/`catch`/`finally` 处理结果、错误、清理。
- Promise:用 `Promise.all` 并行等待全部成功;`Promise.race` 取最先完成;`Promise.allSettled` 等待全部完成;`Promise.any` 取最先成功。
- async/await:用 `async function` 和 `await` 编写异步代码;用 `try/catch` 捕获 `await` 抛出的错误。
- async/await:对相互独立的异步操作使用 `Promise.all` 并行执行;不要顺序 `await` 每个独立操作。
- async/await:需要顺序依赖时再依次 `await`;需要并行时先创建 Promise,再统一 `await Promise.all`。
- 异步错误处理:检查 `response.ok`,失败时抛出 `Error`;用 `catch` 捕获 Promise 链中的错误。
- 异步错误处理:用 `window.addEventListener('unhandledrejection', ...)` 处理未处理的 Promise 拒绝。
- 异步错误处理:用 `fetchWithRetry` 循环重试,并在最后一次重试时继续抛出错误;重试间隔可用 `setTimeout` 递增。
- 模块模式:用 IIFE 封装私有变量和私有函数,只返回公共 API。
- 揭示模块模式:在 IIFE 内定义私有实现,在返回对象中把公开方法映射到私有函数。
- 工厂模式:用 `createUser` 等工厂函数根据角色/配置返回对象,避免直接暴露具体类。
- 单例模式:用 IIFE 保存 `instance`,通过 `getInstance()` 返回唯一实例;或用 ES6 class 在构造函数中检查 `Database.instance`。
- 观察者模式:实现 `EventEmitter`,提供 `on`/`off`/`emit`/`once`;`on` 返回取消订阅函数。
- 记忆化:用 `memoize` 和 `Map` 缓存函数结果;用 `JSON.stringify(args)` 生成 key;注意用 `fn.apply(this, args)` 保留 `this`。
- 命名规范:常量用 `UPPER_SNAKE_CASE`;变量和函数用 `camelCase`;类用 `PascalCase`;私有成员用 `_` 前缀。
- 命名规范:布尔变量用 `is`/`has`/`can` 前缀;函数用动词前缀,如 `getUser`、`setConfig`、`validateInput`、`handleClick`。
- 错误处理:通过继承 `Error` 创建自定义错误类,如 `ValidationError`、`NetworkError`,并设置 `name` 和额外字段。
- 错误处理:抛出具体错误;用 `instanceof` 区分错误类型并分别处理。
- 性能:循环中避免重复计算 `array.length`,可先缓存长度,或优先使用内置数组方法。
- 性能:用 `debounce` 延迟高频操作,如搜索输入;用 `throttle` 限制高频事件,如滚动。
- 性能:用 `Set`/`Map` 做 O(1) 查找,替代数组 `includes` 的线性搜索。
- 性能:使用事件监听后要 `removeEventListener`,避免内存泄漏。
- 性能:用 `WeakMap` 存储私有数据,实例被回收时缓存条目自动消失。
- 代码组织:遵循单一职责,把校验、转换、保存、发邮件、更新 UI 拆成独立函数。
- 代码组织:写纯函数,不修改输入;需要更新对象时返回新对象,如 `{ ...cart, items: [...cart.items, item] }`。
- 代码组织:避免魔法数字,用常量对象如 `ROLES.ADMIN`、`ROLES.EDITOR` 代替裸数字。
- 代码组织:使用默认参数,如 `function greet(name = 'Guest') {}`,不要写 `name = name || 'Guest'`。
- 代码组织:使用守卫从句提前返回,减少嵌套 `if`。
- 内存管理:用 `clearTimeout`/`clearInterval` 清理定时器。
- 内存管理:用 `removeEventListener` 移除事件监听。
- 内存管理:用完的大对象赋值为 `null`,帮助垃圾回收。
- 内存管理:用 `WeakMap`/`WeakSet` 做缓存,避免阻止垃圾回收。
- 内存管理:避免全局变量;用模块或闭包把变量限制在局部作用域。
- 内存管理:闭包只捕获需要的数据,不要无意中保持大对象引用。
- 可测试性:把逻辑写成纯函数,如 `calculateTotal(items)`,避免依赖外部状态。
- 可测试性:用依赖注入,如 `constructor(apiClient)`,不要直接在类内部 `new ApiClient()`。
- 可测试性:把副作用与纯转换分离,先 `transformData`,再执行日志/数据库/UI 更新。
- 数组速查:`map`/`filter`/`reduce` 做转换、过滤、聚合;`find`/`findIndex`/`indexOf`/`includes`/`some`/`every` 做查找和判断。
- 数组速查:变异方法包括 `push`/`pop`/`unshift`/`shift`/`splice`/`reverse`/`sort`;非变异包括 `slice`/`concat`/展开/`join`。
- 对象速查:用 `Object.keys`/`Object.values`/`Object.entries`/`Object.fromEntries` 转换对象。
- 对象速查:用 `Object.assign` 或对象展开合并对象;用 `Object.freeze`/`Object.seal`/`Object.preventExtensions` 控制可变性。
- 对象速查:用 `Object.hasOwnProperty.call(obj, 'a')` 或 `'a' in obj` 判断属性;不要直接调用 `obj.hasOwnProperty`。
- 常见坑:比较用 `===`/`!==`,避免 `==` 的类型强制转换;`null == undefined` 为 `true`,`null === undefined` 为 `false`。
- 常见坑:理解类型强制转换,如 `'5' + 3` 得到 `'53'`,`'5' - 3` 得到 `2`,`+'5'` 得到 `5`,`!!'value'` 得到 `true`。
- 常见坑:普通函数中的 `this` 由调用方式决定;箭头函数使用词法 `this`;对象方法用普通函数才能拿到 `this.name`。
- 常见坑:记住 falsy 值:`false`、`0`、`-0`、`0n`、`''`、`null`、`undefined`、`NaN`。
- 常见坑:数组和对象比较的是引用,`[] === []` 和 `{} === {}` 都为 `false`。
- 常见坑:浮点精度问题,如 `0.1 + 0.2 === 0.3` 为 `false`;用 `Math.abs(a - b) < Number.EPSILON` 判断近似相等。
- 常见坑:`var` 会提升为 `undefined`;`let`/`const` 在初始化前访问会抛 `ReferenceError`,即暂时性死区。
适用边界 · 注意事项
- 当问题涉及具体框架(React/Vue/Angular)、浏览器 DOM 或 Node.js 专有 API 时,不能只依赖本经验,需结合对应文档。
- 当项目已采用 TypeScript 并依赖类型系统、lint 规则与编译期检查时,本经验只能作为运行时与语言语义补充,不能替代类型设计。
- 当需要学习完整 ECMAScript 规范、引擎实现或极端性能调优时,本经验不覆盖。