首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >关掉 AI 写代码一天,我发现自己几乎忘了怎么思考

关掉 AI 写代码一天,我发现自己几乎忘了怎么思考

作者头像
前端达人
发布2026-06-29 15:27:44
发布2026-06-29 15:27:44
280
举报
文章被收录于专栏:前端达人前端达人

我想问你一个问题,认真想一想再回答:

你上次写 useEffect,你知道为什么要在里面 return 一个函数吗?

不是「大概知道」,不是「好像是清理用的」,而是真的能说清楚——不写会发生什么,什么情况下会出问题,出了问题会报什么错。

如果你能说清楚,这篇文章你可以快速扫一眼。

如果你的第一反应是「这个我用过,但让我解释……等我想想」——那我们聊聊。

这不是你的问题,是一种新的学习方式带来的副作用

先说清楚:这不是在批评谁。

我们这一代学前端的人,赶上了一个神奇的时间窗口——AI 工具爆发的时候,刚好是很多人入门的时候。用 Claude、Cursor、Copilot 写代码,比查文档快十倍,比翻 StackOverflow 快二十倍。

这本来是一件好事。

但它悄悄带来了一个副作用:你开始习惯拿到能跑的代码,而不是习惯理解代码为什么能跑。

这两件事,差距比你想象的大。

先来看一个你肯定写过的代码

做一个简单的需求:页面加载完,调接口拿数据,显示出来。

AI 给的代码大概是这样:

代码语言:javascript
复制
import { useState, useEffect } from'react'

function UserList() {
const [users, setUsers] = useState([])

  useEffect(() => {
    fetch('/api/users')
      .then(res => res.json())
      .then(data => setUsers(data))
  }, [])

return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  )
}

代码跑通了。页面有数据了。你提交了。

但我问你几个问题——

useEffect 后面那个空数组 [] 是干嘛的?如果不传,会有什么后果?如果里面传了一个变量,行为又有什么不同?

useState([]) 为什么初始值是空数组,而不是 null 或者 undefined

setUsers(data) 调用之后,页面是立刻重新渲染,还是等一会儿?

这些问题,你能流畅回答几个?


我不是要考你,而是想说明一件事:如果你只是把 AI 的代码复制过来改改,这几个问题你很可能回答不上来。因为 AI 给你的是结果,不是过程。它不会告诉你「我为什么要写这个 []」,它只会给你一份能跑的代码。

useEffect 这件事,值得认真说一次

很多初学者把 useEffect 理解成「页面加载完执行一次的地方」,然后就这么用了。

这个理解没有大错,但只说对了一小部分。

真正的理解是这样的:

代码语言:javascript
复制
React 的渲染模型

用户操作 / 数据变化
      │
      ▼
React 重新渲染组件(函数重新执行)
      │
      ▼
更新 DOM
      │
      ▼
执行 useEffect(在 DOM 更新之后)
      │
      ├─ 依赖数组 [] → 只在挂载时执行一次
      ├─ 依赖数组 [count] → count 变化时重新执行
      └─ 没有依赖数组 → 每次渲染后都执行

这个流程,是 React 运转的核心逻辑。

如果你理解这个图,你就能回答为什么 [] 意味着只执行一次——因为没有任何依赖会变化,所以不会重新触发。

如果你不理解这个流程,当某天接口被重复调用了,或者数据更新不符合预期,你会不知道从哪里入手。

AI 给了你能跑的代码,但没有给你这张图。

那道让我停下来的算法题

我说一件我自己的事。

前段时间我在做一个音频功能,需要记录用户听过哪些时间段。后端存的是一个区间数组:

代码语言:javascript
复制
[[0, 19], [29, 65], [80, 120]]

每次用户新听了一段,我要把这段合并进去,去掉重叠,存一份干净的结果。

我当时的第一反应——是打开 AI 对话框,准备把这个需求粘进去。

然后我停了下来。

我拿出纸,画了一条数线:

代码语言:javascript
复制
已有:   [0──19]    [29──────65]    [80──────120]

新来:         [15──────35]

分析每个已有区间:
  [0,19]  和 [15,35]: 19 > 15,重叠 → 合并 → [0,35]
  [29,65] 和 [15,35]: 35 > 29,重叠 → 继续合并 → [0,65]  ← 这里容易漏掉!
  [80,120] 和 [15,65]: 65 < 80,不重叠 → 保留

结果: [0──────65]    [80──────120]

手推的时候发现一个我一开始没想到的边界:新区间不只是和一个已有区间重叠,可能和多个区间都有重叠,要一路合并下去。

如果直接用 AI,它会给我正确答案——但我不会经历发现这个边界的过程。下次遇到类似的多段合并场景,我还是不知道要注意这一点。

我花了三十分钟,最后写出来的代码:

代码语言:javascript
复制
function mergeRanges(existing, newRange) {
const [newStart, newEnd] = newRange
let start = newStart
let end = newEnd
const others = []

for (const [s, e] of existing) {
    // 完全不重叠:新区间在左边,或者在右边
    if (e < start || s > end) {
      others.push([s, e])
    } else {
      // 重叠:扩展边界
      start = Math.min(start, s)
      end = Math.max(end, e)
    }
  }

  others.push([start, end])
return others.sort((a, b) => a[0] - b[0])
}

测试时还是漏了一个 edge case,改了一次。

但这段代码我能解释每一行。不是因为我记住了,是因为我想出来的。

再聊聊 async/await,另一个「会用但不懂」的重灾区

问你一个问题:下面这段代码,console.log 的输出顺序是什么?

代码语言:javascript
复制
console.log('1')

setTimeout(() => {
  console.log('2')
}, 0)

Promise.resolve().then(() => {
  console.log('3')
})

console.log('4')

如果你的第一反应是「1 4 2 3」或者「1 2 3 4」,说明你对 JavaScript 的执行机制还没有真正理解。

正确答案是 1 → 4 → 3 → 2

为什么?因为 JS 的事件循环分三层:

代码语言:javascript
复制
JavaScript 执行顺序

同步代码(主线程)
  │  最先执行
  ▼
微任务队列(Microtask)
  │  Promise.then / queueMicrotask 在这里
  │  同步代码执行完立刻清空
  ▼
宏任务队列(Macrotask)
  │  setTimeout / setInterval / DOM 事件 在这里
  │  每次事件循环取一个执行
  ▼
(循环回去继续)

所以:console.log('1')console.log('4') 是同步代码,先跑。Promise.then 是微任务,同步结束后立刻跑,所以 32 前面。setTimeout 是宏任务,最后跑。

这张图理解了,你就能看懂为什么 async/await 的等待不会卡死页面,为什么某些异步操作的结果拿到得比你预期的晚,为什么接口请求的顺序偶尔会乱。

用 AI 写 async 代码很容易。但这些问题出现的时候,AI 不会告诉你为什么。

会用和理解,差的不只是一点点

我打个比方。

你去学炒菜。老师给你写好了菜谱:几勺盐、几勺酱油、火候多大、翻炒几下。你照着做,菜端上桌,不难吃。

这是 AI 给代码的方式。

但如果你只会照菜谱,某天菜谱里没有这道菜——你就不会做了。更麻烦的是,某天菜太咸了,你不知道是盐放多了还是酱油太多,因为你从来没有真正理解「咸度是怎么来的」。

真正的厨师能做到:给我几样食材,我告诉你能做什么菜;这道菜少了某个调料,我知道用什么替代;出了问题,我能找到问题在哪一步。

这种能力,不是照着菜谱做出来的。是经历了很多次「这道菜为什么不对」之后磨出来的。

写代码也一样。

能用 useEffect 发请求,不等于理解了 React 的渲染流程。能用 async/await 等待数据,不等于理解了 JS 的事件循环。能用 AI 生成一个完整页面,不等于理解了状态和副作用是怎么协作的。

差距在调试的时候才会暴露。那个时候 AI 给你的不是答案,是几个猜测——真正能判断哪个猜测是对的,需要你自己的基础理解。

一个让我印象深刻的对比

我们团队有个刚入职的同学,能用 AI 很快写出一个功能完整的 React 表单:输入验证、提交、错误提示、加载状态全有。

有一天这个表单出 bug 了:某个输入框的内容,在提交之后不会清空。

他把 bug 描述给 AI,AI 给了三个可能的原因,他逐一试,花了一个小时,没找到。

我看了一眼代码,发现问题:他在 onSubmit 里直接 setFormData({}) 清空了 state,但在同一个函数里紧接着又读了 formData 的值——而在 React 里,state 更新不是立即生效的,同一次渲染里你读到的还是旧值。

这个 bug,如果他理解 React 的 state 更新机制,两秒钟就能看出来。因为他没有这个理解,AI 给他的几个猜测他也分辨不了哪个是正确方向。

代码是 AI 写的,但出了问题,你得自己懂。

这就是现实。

最厉害的那些人,是这样用 AI 的

我观察过身边几个技术强的同事,他们不是不用 AI——他们每天都在用,用得比一般人还多。

但区别在于,他们在打开 AI 之前,会先在草稿上写几行:

  • 这个问题的边界情况是什么?
  • 我目前的思路是什么,哪一步走不通?
  • 我想用什么数据结构,为什么?

写完再去问。

这样问出来的问题质量完全不一样——AI 给的方案,他们能立刻判断对不对、有没有考虑某个边界、用了什么原理。遇到 AI 答错了,他们也能发现。

用 AI 之前先想,和直接把问题扔给 AI,两种用法,两种成长速度。

说给初学者听的话

如果你现在刚开始学前端,我特别想说这几件事:

先搞懂 useState 真正在做什么,再用 AI 帮你写状态逻辑。

它不是一个「存变量的地方」,它触发的是整个组件的重新渲染。你改了 state,React 会重新执行你的整个组件函数,重新生成 JSX,再去更新 DOM 里真正需要改的地方。理解这个,很多奇怪的 bug 就能看懂了。

先理解 useEffect 是什么时机执行,再用它调接口。

它不是「页面加载的地方」,它是「渲染完成之后的副作用执行器」。依赖数组控制的是「什么情况下重新执行」,而不是「执行几次」。

先弄清楚 Promise 是什么,再用 async/await。

async/await 只是 Promise 的语法糖,让异步代码看起来像同步代码。理解了 Promise 的状态(pending、fulfilled、rejected),你才能真正看懂 .catch() 在做什么,.finally() 什么时候会跑。

这些不是要你死记硬背,而是要你真正用过、踩过坑、想明白

这个过程,AI 可以帮你,但不能替你经历。

一个值得记住的区别

有两种「会用」:

第一种:你能让代码跑起来。

第二种:你知道它为什么能跑起来,以及——当它跑不起来的时候,你知道为什么。

第一种,现在的 AI 工具已经能给任何人了。

第二种,只能靠你自己积累。

代码语言:javascript
复制
两种「会用」的差距

         AI 能帮你到这里
              │
              ▼
    ┌─────────────────┐
    │   代码能运行     │
    └─────────────────┘
              │
     这段路要自己走
              │
              ▼
    ┌─────────────────┐
    │ 理解为什么能运行 │
    └─────────────────┘
              │
              ▼
    ┌─────────────────┐
    │ 出问题能找到原因 │
    └─────────────────┘
              │
              ▼
    ┌─────────────────┐
    │ 能设计出新的方案 │
    └─────────────────┘

第二、三、四层,是你真正的技术能力。AI 帮你到第一层,剩下的在你自己身上。

最后说一件事

那道区间合并题,我手推了三十分钟,最后写出来的代码,我现在还记得思路。

如果当时问了 AI,代码早就提交了,我现在什么都不记得。

AI 让你跑得快,但如果你一直跑在别人给你铺的路上,你自己找路的能力会慢慢退化。

这不是 AI 的错,是我们用它的方式的问题。

很多人担心 AI 会替代程序员。我觉得更现实的风险是另一个:AI 把「写出能跑的代码」这件事变简单了,但调试、架构、判断——这些事还是得靠人。能做这些事的人,价值只会越来越高;只会让 AI 跑代码的人,才真的会被替代。

从现在开始,每隔一段时间,给自己一道题,关掉 AI,自己做一遍。

不是为了证明什么,是为了确认:你的思考能力,还在。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端达人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 这不是你的问题,是一种新的学习方式带来的副作用
  • 先来看一个你肯定写过的代码
  • useEffect 这件事,值得认真说一次
  • 那道让我停下来的算法题
  • 再聊聊 async/await,另一个「会用但不懂」的重灾区
  • 会用和理解,差的不只是一点点
  • 一个让我印象深刻的对比
  • 最厉害的那些人,是这样用 AI 的
  • 说给初学者听的话
  • 一个值得记住的区别
  • 最后说一件事
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档