# 第 1 篇|为什么前端也要懂算法(AI 时代也一样)

7 阅读5分钟

「凡事应该力求简单,但不能更简单。」——阿尔伯特·爱因斯坦


本篇干啥

「我又不刷 LeetCode,写页面要啥算法?」——页面照样要算账:CPU 和网速就那么多,顺不顺,常取决于你多干了多少遍无用功(循环套娃、重复扫表之类)。这层直觉不神秘,跟有人叫「性能优化」、有人叫「架构」是同一条底裤

AI 时代多一嘴:现在不少活是模型「啪」一下生成出来的,爽是爽,副作用也很实在——有人很久没正经单步调试过(断点、看调用栈、盯变量怎么变),有人连最简单的排序都手写不顺(不是要你默写快排上生产,而是脑子里没「比较、交换、循环怎么转」这根弦)。工具再强,验货、改错、收窄范围还得人来;基本功薄了,AI 写的是「能跑」还是「坑你」,你很难第一时间分辨。所以本系列仍然站**「懂一点、能动手验证」**这一边,不是鼓吹全民刷爆 hard。

动笔前先想清动机:为啥学、学到啥程度就收手——有目的才不糟蹋时间。下面一段专门给动机「拧干毛巾」,不制造焦虑,也不灌鸡汤


先认清:算法不是银弹,也别和工程能力绑死

不是为了面试,却打算用业余大头时间死磕刷题?坦白说,多半不如把同等时间砸在工程上:需求拆解、可维护代码、构建与性能、协作流程——这些才是前端日常的主战场。

有人说刷了题就「变强」、写项目能超神——真没那么玄幻。软件工程里早有人说过:没有银弹。(行业黑话:银弹=「一招包治百病」的神话解药;出自 Brooks 的《没有银弹》,论文不长,好奇可以读。)把算法当银弹,是典型的误会。

工程能力说白了是解决问题:写得出、拆得动、接得住线上幺蛾子。算法训练能帮你更严谨、多点思路,但提速曲线通常不如直接做项目陡。想补短板,设计模式、前端性能优化往往更「对口」——这话不讨喜,但是实话。

业务里复杂算子常有现成库;真卡住的,常常是需求、状态、协作,而不是「你会不会手写快排」。行业里工程极强、二叉树手生的前辈大有人在——所以:算法厉不厉害,和工程牛不牛,别强行画等号;具体问题具体投入。

对不少前端同学,学数据结构算法最实在的一笔账仍是:面试用、谈 offer 有底气——认清这个不丢人。反过来,「学完就晋升加薪」类广告,听听就好,别被焦虑牵着买单

那这专栏还写啥? 写一点低成本、高频率用得上的直觉(比如别写「全班握手」式循环),顺便给 AI 时代留条审代码的底线——不是劝你把 LeetCode 当主业。


懂算法 ≠ 刷题

刷题像健身房;上班像搬快递。健身房练动作,上班要问:这一车货,我搬几趟能累死?

若你主要诉求是工程,这里的目标是够用就好三件事:

  • 看见循环套 find / filter,心里嘀咕一句:列表一长会不会腿软
  • 知道 Map / Set 不是玄学,是「多花点内存,少跑两圈」的买卖。
  • 跟产品对线时能讲:这里全量算是 n² 的活儿,要么分页要么改交互——对方会觉得你不好糊弄

下篇正式讲 时间 / 空间复杂度;本篇先把为啥学、学到哪算够说清楚。


快餐店与快递(30 秒版)

  • 笨厨房:来一单,把今天所有单子从头看一遍再动手——单多了,厨师先疯。
  • 正常厨房:排队出餐,先来先做。

快递同理:每个包裹和全仓库比一遍小区,和先按邮编分堆,不是一个物种的工作量。

界面也一样:同样的 UI,遍历方式不同,用户眼里可能是「丝滑」和「PPT」。你先不用会算大 O,先问自己一句:我在干笨厨房还是正常厨房?


AI 写得快,你还得会踩刹车

审代码

AI 很爱产「能跑」的代码:嵌套循环去重、循环里 includes——小样例永远正确,数据量上来当场表演卡死。你不会数复杂度,就看不出该换成 Set;合并进主分支的 Git 作者是你。

会提问

你说「括号匹配」它瞎蒙也能写;你说「用栈记没配对的左括号」——规格清楚,输出才稳。基本功=你能把需求压缩成它听得懂的关键词

背锅位

白屏、掉帧、内存爆炸——复盘找谁?找提交记录里的人。 AI 是副驾导航:油门刹车还在你脚下。(不焦虑、不踩工具:AI + 基本功才是完整打法。)


举个栗子:名单里有没有「重名」?

问题:一串名字,判断有没有出现过两次相同的

  • 笨办法:拿第一个跟后面都比一遍,再拿第二个跟后面都比……像全班两两握手,人多了要握疯。
  • 巧办法:准备一个小本本(Set),念到一个名字先查本本上有没有——只扫名单一遍
// 笨:两层循环,两两比对
function hasDupSlow(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] === arr[j]) return true;
    }
  }
  return false;
}

// 巧:扫一遍,用 Set 记「见过谁」
function hasDupFast(arr) {
  const seen = new Set();
  for (const x of arr) {
    if (seen.has(x)) return true;
    seen.add(x);
  }
  return false;
}

const names = ['张三', '李四', '王五', '李四'];
console.log(hasDupSlow(names)); // true
console.log(hasDupFast(names)); // true

本篇只要记住:同样都能跑通,第二种人少的时候差不多,人(数据)一多,第一种会明显更慢。具体怎么数「慢多少」,下篇讲。


小练习

  1. 造一个长度约 3000 的名字数组(可用数字当名字:Array.from({ length: 3000 }, (_, i) => 'user-' + i)),用 console.time 分别跑 hasDupSlowhasDupFast(没有重复时两者都应返回 false),看耗时差。
  2. 打开你项目里带 includes / find 的循环,想一想:列表变长,会不会变成「全班握手」?

面试一句

「算法强项≠工程全能;但看得懂复杂度,少踩『全班握手』,面试和线上都少挨揍。」


下篇

第 2 篇 · 代码的时间与空间复杂度——O(1) / O(n) / O(n²) 怎么数,继续 纯 JS,不讲数学系黑话。