JavaScript 进阶:从「能跑」到「好维护」

这篇笔记重点不在 API 清单,而是想通过几个关键概念——作用域、闭包、异步——重新整理我对 JavaScript 的理解。

前端开发场景,屏幕上显示 JavaScript 代码与浏览器预览

一、从「在全局乱放东西」到「把变量关进房间」

学前端最容易踩的坑之一,就是全局变量到处飞。 刚开始写 Demo 可能看不出问题,但一旦项目稍微变大,调试就像在一团乱麻里找线头。

作用域(scope)可以理解成一间间「房间」:

  • 全局作用域 = 整个房子;
  • 函数作用域 = 每个独立的小房间;
  • 块级作用域(let/const) = 某个角落的小隔间。
房间结构示意图,比喻变量作用域
把变量锁在合适的「房间」里,是可维护代码的第一步。
实践感受:有意识地减少全局变量,尽量使用constlet,单这一步就能让 bug 数量明显下降。

二、闭包:不是魔法,而是「把房间钥匙带出来」

闭包经常被讲得很玄乎。其实可以这样想: 闭包就是函数记住了它创建时所在的那间房间

function createCounter() {
  let count = 0; // 房间里的私有变量

  return function () {
    count++;
    console.log('当前次数:', count);
  };
}

const counter = createCounter();
counter(); // 1
counter(); // 2

这里的 createCounter 就像一个工厂,每次调用都会创建一个「带钥匙的人」 (内部函数),它可以在之后的任何时刻,继续访问当时房间里的 count

三、异步:学会和「未来」打交道

浏览器世界里,到处都是异步:网络请求、定时器、事件监听……如果不理解异步,代码就会写成一层层回调地狱。

时钟与日程本,象征异步与时间管理
可以把 Promise 想象成一张「未来会完成的任务单」。

现在我更喜欢把 Promise 理解成一张「任务凭证」:

  • 刚创建时是 pending,任务还在进行中;
  • 成功就是 fulfilled,可以在 .then 里读取结果;
  • 失败就是 rejected,在 .catch 里处理错误。
async function fetchUser() {
  try {
    const res = await fetch('/api/user');
    const data = await res.json();
    console.log('用户信息:', data);
  } catch (err) {
    console.error('请求失败:', err);
  }
}

async/await 的好处是:让异步代码看起来更像同步逻辑, 更贴近我们脑海中「先做 A,再做 B」的思考方式。

四、从今天起写「给半年后自己看的代码」

📝 给未来自己的三条约定
  1. 变量和函数名尽量写成「一句话的缩写」,而不是单个字母;
  2. 函数不要太长,一屏能看完最好;
  3. 遇到绕脑袋的逻辑,给半年后的自己留一行解释性的注释。

写到这里,这篇笔记更像是对自己的一次「代码复盘」。 也许几年之后再回来看,会有完全不同的理解,那就再记一篇新的就好。