JavaScript 并不天生难,真正难点在于执行模型、异步机制和对象动态性;undefined 是未赋值的默认状态,null 是主动声明的空值;=== 比 == 更安全;?? 比 || 更精准处理空值;catch 只捕获前一个 Promise 的 rejection;this 由调用方式决定,箭头函数继承外层 this。

JavaScript 并不天生难,但它的“灵活”和“隐式行为”常让人误以为难——真正卡住人的,往往不是语法本身,而是对执行模型、异步机制和对象动态性的误解。
为什么 undefined 和 null 总分不清?
这不是记不住,是没看到它们在引擎里的真实角色:undefined 是变量声明了但没赋值的默认状态;null 是开发者主动表示“这里本该有值,但现在为空”的信号。类型检查时用 === 比 == 更安全,因为后者会强制转换:
console.log(null == undefined); // true console.log(null === undefined); // false
- 函数参数未传入时,形参值为
undefined,不是null -
void 0是获取原始undefined值最可靠的方式(防篡改) - 用
??(空值合并)处理可能为null或undefined的情况,比||更精准
Promise 链里为什么 catch 捕不到错误?
常见错觉:只要最后加个 .catch() 就万事大吉。实际它只捕获前一个 Promise 的 rejection,如果中间某步用了 try/catch 却没 throw,或写了 .then(success, fail) 但 fail 函数内部出错,错误就丢了。
- 推荐统一用
.then().catch()链式写法,避免在.then()的第二个参数里处理错误 - 异步函数中抛出的错误不会自动转为 Promise rejection,必须用
throw或返回被 reject 的 Promise - 全局监听
unhandledrejection事件,能帮你发现漏掉的 Promise 错误
为什么 this 在回调里总是不对?
根本原因:JavaScript 的 this 不由函数定义位置决定,而由 ** 调用方式 ** 决定。箭头函数没有自己的 this,它继承外层 作用域 的 this,这是最常用解法:
立即学习“Java 免费学习笔记(深入)”;
class Button {constructor() {this.label = 'Click me';} handleClick() { console.log(this.label); // 正确输出 } init() { // ❌ 普通函数:this 指向 button 元素,不是实例 document.getElementById('btn').onclick = this.handleClick; // ✅ 箭头函数:this 保持指向实例 document.getElementById('btn').onclick = () => this.handleClick(); // ✅ 或显式绑定 document.getElementById('btn').onclick = this.handleClick.bind(this); } }
- 事件 处理器、定时器、数组方法(如
map)的回调里,this默认丢失 - 类字段写法
handleClick = () => {……}自动绑定,但注意它每次实例化都会创建新函数 - 不要依赖
arguments.callee或caller,它们在严格模式下禁用
最难的部分不在 API 数量,而在调试时能否快速判断:这个值是从哪来的?这个 this 到底绑在哪?这个 Promise 是被谁 resolve 的?把执行上下文、原型链和微任务队列当成日常排查 工具,比死记语法重要得多。