面试里的资历深浅,从来不看你说了多少。下面每一组回答都是对的,但每组里只有一个能帮你拿到录用通知,而这个差距比大多数人以为的更小、也更容易学会。
当工程师问“高级工程师的回答听起来是什么样”,通常得到的建议是:更自信一点,或者多谈谈影响。这话不算错,但模糊到没法用。
四个可复制的差别
下面给点更具体的东西。一组接一组看下来,高级回答只在四个地方不一样:说出底层的机制,指向具体场景而不是泛泛而谈,主动讲清代价,以及说明自己会测量什么。没有别的。一旦你能看出来,你就能做到。
闭包:初级与高级的差距
初级回答:闭包是一个函数,它记得定义时所在作用域里的变量,所以即使外层函数已经返回,它之后仍然能用这些变量。
高级回答:它是一个函数,加上对它被创建时所在作用域的引用,所以它捕获的变量会留在堆上,而不是随着调用结束一起死掉。这正是模块模式和钩子能工作的原因,也是经典的内存泄漏来源:在一个长期存活的处理器里闭包住了某个大对象,它就永远不会被回收。这也解释了人们用 var 时遇到的循环陷阱——因为一个共享的绑定被捕获了,而不是每次迭代各有一个。
这里的追问几乎总是循环陷阱或者内存泄漏。如果你主动把两个都讲了,等于已经提前回答了追问。
循环陷阱的代码真相
面试里常出现的版本是这样的:
for (var i = 0; i < 3; i++) {setTimeout(() => console.log(i), 0);// 3, 3, 3 -- 一个 i 的绑定,被三个闭包共享for (let i = 0; i < 3; i++) {setTimeout(() => console.log(i), 0);// 0, 1, 2 -- let 每次迭代创建一个新的绑定知道它打印 3, 3, 3 只是入场券;能用“绑定”来解释为什么,才是真正的答案。
性能优化:先诊断还是先动手
初级回答:我会把昂贵的组件用 memo 包起来,再用 useMemo 和 useCallback,这样它们就不会不必要地重新渲染。
高级回答:首先我会搞清楚这到底是不是一个渲染问题。分析器会告诉你,你是重新渲染太频繁、一次渲染太多,还是卡在跟 React 完全无关的事情上。我上次做的那个页面,问题出在一个 context 每次渲染都持有新对象,所以每个消费者在每次按键时都重新渲染。把 context 拆开就解决了。我会在测量之后才用 memo,因为到处乱加会增加比较成本,还会给不读依赖数组的人带来一堆过期闭包的问题。
初级回答会引出“那 memo 比较的是什么?”这种追问。高级回答已经把对话推进到了诊断环节,而那正是面试官想聊的地方。
异步非阻塞:一句话的深度差异
初级回答:因为它是非阻塞且异步的,所以能同时处理很多请求,不用等每一个完成。
高级回答:因为 I/O 是……
热门跟贴