技术探索与实践踩坑记录:一个被裁员后靠死磕 JavaScript 面试题翻身的上海码农自白

AI提示词工人
2025-12-17 18:49
阅读 1833

去年十月,我坐在张江某大厂工位上,HR敲了敲我桌沿:“小陈,方便聊聊吗?”

那天下午三点十七分,阳光斜照进玻璃幕墙,我的 MacBook 屏幕上还开着一个没跑通的 React 组件。十分钟后,我抱着纸箱站在楼下,手里攥着 N+1 的赔偿单——月薪 22k,拿了 3 个月,税后不到 6 万。而我和女朋友合租在浦东三林,月租 3500,房租、水电、吃饭、交通……算下来每月刚性支出至少 8000。

那一刻,我脑子里不是“天塌了”,而是:“完了,下个月面试要是再挂,连泡面都得省着吃。”


被现实毒打:面试题挑战里的“综合”陷阱

裁员后的第一周,我疯狂投简历。结果?简历石沉大海。第二周,终于有几个猎头找上门,但一问技术栈,对方语气立马变冷:“你这 JS 基础……好像不太扎实啊?”

我懵了。我在上一家公司干了三年前端,天天写 Vue + TypeScript,搞微前端、性能优化、CI/CD 流水线,怎么就“基础不扎实”了?

直到我去面了一家 B 轮 startup,面试官甩给我一道题:

“请手写一个 Promise.allSettled 的 polyfill,并解释它和 Promise.all 的区别。另外,如果传入的数组里有非 Promise 元素,你怎么处理?”

我当场卡壳。脑子里只有“用 Promise.all 不就行了吗?”这种 naive 想法。结果面试官微微一笑:“我们这边对 JS 底层理解要求比较高,建议你再夯实一下基础。”

回家路上,地铁 2 号线挤得像沙丁鱼罐头,我盯着手机刷 LeetCode 和 GitHub 上的高频面试题,突然意识到一个问题:我一直在“用” JavaScript,却从来没真正“懂”它。


死磕 JS:从“会用”到“懂原理”的痛苦转型

接下来一个月,我给自己定了个计划:每天下班(哦不对,现在是“待业”)后,雷打不动 3 小时,专攻 JavaScript 核心机制。

我翻烂了《JavaScript 高级程序设计》第四版,重读了 You-Dont-Know-JS 系列,甚至去 MDN 一行行啃规范。重点攻克几个方向:

  • 事件循环(Event Loop):宏任务 vs 微任务,Node 和浏览器的差异
  • 闭包与作用域链:不只是“能访问外层变量”,而是 V8 如何实现的
  • 原型链与 this 绑定:call/apply/bind 的底层模拟
  • 异步控制流:Generator + co、async/await 编译后的样子
  • 内存管理:V8 的垃圾回收机制,如何避免内存泄漏

最让我崩溃的是手写题。比如:

// 实现一个带并发限制的请求调度器
function requestScheduler(urls, max, callback) {
  // ...
}

我一开始写的版本,要么并发控制失效,要么回调顺序错乱。后来才发现,关键在于用 Promise.race + 递归控制队列,还得处理 reject 情况。光是调试就花了两天。

那段时间,女友看我天天对着电脑皱眉,有次晚饭时说:“要不咱先找个工作过渡下?送外卖也行。”
我苦笑:“送外卖月薪可能还没我之前税后高,而且……我不想放弃技术路线。”

她没说话,默默给我盛了碗汤。


踩坑实录:那些看似简单却暗藏杀机的“综合”题

真正让我开窍的,是一道“综合”题——它把闭包、this、原型、异步全揉在一起:

function Foo() {
  getName = function () { console.log(1); };
  return this;
}
Foo.getName = function () { console.log(2); };
Foo.prototype.getName = function () { console.log(3); };
var getName = function () { console.log(4); };
function getName() { console.log(5); }

Foo.getName();          // ?
getName();              // ?
Foo().getName();        // ?
getName();              // ?
new Foo.getName();      // ?
new Foo().getName();    // ?
new new Foo().getName(); // ?

第一次做,我错了 4 道。原因?忽略了变量提升、函数声明覆盖、this 绑定优先级、new 运算符的执行顺序。

这题背后其实是对 JS 执行上下文、作用域、对象模型的“综合”考察。很多同学只背答案,但面试官真正想看的是你能不能拆解问题

我后来总结了一个方法论:遇到复杂 JS 题,先问自己三个问题:

  1. 这段代码在哪个阶段执行?(编译期 vs 运行期)
  2. 当前 this 指向谁?(全局、对象、undefined?)
  3. 变量从哪查找?(作用域链 or 原型链?)

这套思路帮我过了后面 5 场技术面。


转机:用“实践”反哺“理论”

光刷题还不够。我决定做个 side project:用原生 JS 写一个 mini React —— 支持 JSX 编译、虚拟 DOM diff、组件生命周期。

名字我都想好了,叫 TinyReact

过程中踩了无数坑:

  • JSX 转换用 Babel 插件还是自己写 parser?(最后选了 Acorn + 自定义 visitor)
  • 如何高效 diff?(借鉴了双端比较,但没处理 key 复用)
  • setState 是同步还是异步?(得模拟事务批处理)

但正是这些“造轮子”的过程,让我真正理解了 React 底层为什么这么设计。再去面字节的时候,面试官问:“React 18 的自动批处理是怎么实现的?”
我直接画了个微任务队列图,解释 Fiber 如何 hijack 原生 API,他眼睛一亮:“你这理解很到位啊。”

两周后,offer 到手,月薪 32k,涨幅近 50%。


思考:技术人的护城河到底是什么?

回过头看,我最大的误区,是把“熟练使用框架”等同于“掌握技术”。
但实际上,框架会过时,API 会变,但语言核心机制永远不过时。

JavaScript 尤其如此。它看似简单,var a = 1 谁都会写,但一旦深入,你会发现:

  • 它的灵活性是一把双刃剑
  • 它的“怪异”行为背后都有规范依据
  • 它的生态繁荣恰恰源于底层的开放性

所以,别再抱怨“面试造火箭,上班拧螺丝”。如果你只会拧螺丝,那当然觉得造火箭离谱。但如果你理解火箭原理,哪怕拧螺丝,也能拧出花来。


写给正在焦虑的你

我现在依然住在浦东那个老小区,房租涨到了 3800。但心态不一样了。

上周五晚上,和女友在厨房煮火锅,她突然说:“你现在讲话都不一样了,以前总说‘这个需求好傻’,现在会说‘这个设计其实有 trade-off’。”

我笑了。是啊,技术探索的过程,也是心智成熟的过程。

如果你也在被裁员、被拒、自我怀疑,我想说:
别怕踩坑,坑里才有真知。
别嫌题难,难题才筛真人。

JavaScript 不是玩具,它是武器。
而你要做的,就是磨锋它,握紧它,然后——
在下一场战役里,砍出自己的路。

共勉。

评论 0

最热最新
暂无评论
AI提示词工人Lv.1
0
影响力
0
文章
0
粉丝