圖片來(lái)自于 unsplash 上的 rawpixel
重要說(shuō)明 本文并不會(huì)列出在 React 工作面試中會(huì)出現(xiàn)的常規(guī)問(wèn)題和問(wèn)題的完整回答。這篇文章的重點(diǎn)是展示我提出的問(wèn)題,我在答案中尋找的內(nèi)容以及為什么沒(méi)有不好的答案。如果你想要一份“最佳面試問(wèn)題2018”的集合,請(qǐng)查看 https://github.com/sudheerj/reactjs-interview-questions
我的部分工作職責(zé)是執(zhí)行所謂的“技術(shù)面試”,在面試時(shí)我會(huì)評(píng)估申請(qǐng)“React 前端開發(fā)”職位的潛在候選人。
如果你曾經(jīng)用谷歌搜索“React 面試問(wèn)題”(或任何其他“[技術(shù)]面試問(wèn)題”),你可能已經(jīng)看過(guò)無(wú)數(shù)“十大 React 面試問(wèn)題”,這些問(wèn)題要么已經(jīng)過(guò)時(shí),要么和“state 和 props 之間有什么不同”或“什么是虛擬 dom” 這些問(wèn)題重復(fù)。
知道這些問(wèn)題的答案不應(yīng)該是面試官?zèng)Q定是否錄用你的依據(jù)。這些知識(shí)點(diǎn)都是候選人在日常工作中需要了解,理解和實(shí)現(xiàn)的。如果你被問(wèn)到這樣的問(wèn)題,要么是面試你的人沒(méi)有技術(shù)背景(HR 或“獵頭”),要么他們認(rèn)為這是一種形式。
面試不應(yīng)該浪費(fèi)時(shí)間。它應(yīng)該讓你了解候選人的過(guò)去經(jīng)歷,過(guò)去的知識(shí)和發(fā)展機(jī)會(huì)。候選人應(yīng)該了解您的公司和項(xiàng)目(如果可能),并得出他的表現(xiàn)是否符合你對(duì)這個(gè)職位候選人的期望的反饋。在求職面試中沒(méi)有不好的答案(除非問(wèn)題嚴(yán)格是技術(shù)性的)—— 他的答案應(yīng)該能讓你審視這個(gè)人的思考過(guò)程。
本篇文章以面試官的視角所寫!
讓我們相互了解對(duì)方
在許多情況下,面試將通過(guò) Skype 或其他語(yǔ)音(或語(yǔ)音+視頻)通信平臺(tái)進(jìn)行。嘗試去了解有可能成為員工的人是一個(gè)讓他們放開自己的好方法。
你能告訴我一些你以前的工作,你是如何適應(yīng)團(tuán)隊(duì)的嗎?你的職責(zé)是什么?
了解這個(gè)人在他以前的公司做了什么(如果他被允許分享的話)是一個(gè)很好的開始。這給你一些關(guān)于他以前工作經(jīng)驗(yàn)的基本想法:軟技能(“我是……的唯一開發(fā)人員”,“我和我的同事……”,“我管理了一個(gè)由 6 名開發(fā)人員組成的團(tuán)隊(duì)……”)和硬技能(“ ……我們創(chuàng)建了一個(gè)一百萬(wàn)人使用的應(yīng)用程序”,“……我?guī)椭鷥?yōu)化了應(yīng)用程序的渲染時(shí)間”,“……創(chuàng)建了很多自動(dòng)化測(cè)試”)。
對(duì)你來(lái)說(shuō) React 的主要賣點(diǎn)是什么。為什么你選擇使用 React?
我并不期望你提到 JSX,VDOM 等等。—— 我們已經(jīng)可以通過(guò)閱讀 React 主頁(yè)上的“特色”導(dǎo)語(yǔ)得到這些東西。你 為什么使用 React?
是因?yàn)椤耙咨鲜郑y掌握” 的 API(和其它解決方案相比它的確是非常輕量)?好 —— 這么說(shuō)的話,意味著你愿意學(xué)習(xí)新事物,并且隨學(xué)隨用。
是因?yàn)楦嗟摹熬蜆I(yè)機(jī)會(huì)”嗎?不錯(cuò) —— 你是一個(gè)能夠適應(yīng)市場(chǎng)的人,并且在下一個(gè)大框架到來(lái)的 5 年內(nèi)不會(huì)有任何問(wèn)題。我們已經(jīng)有足夠的 jQuery 開發(fā)人員了。
想想這有點(diǎn)像“電梯游說(shuō)”情景(你和你的老板在電梯里,并且需要說(shuō)服他在 20 樓走出電梯門之前使用新技術(shù))。我想知道你是否了解 React 能給用戶和開發(fā)者帶來(lái)什么好處。
讓我們開始聊些更有技術(shù)性的問(wèn)題
正如我在一段開頭提到的那樣 —— 我不會(huì)問(wèn)你 VDOM 是什么。我們都知道它,但我會(huì)問(wèn)你……
什么是 JSX 和我們?cè)鯓釉?JavaScript 代碼中書寫它 —— 瀏覽器是如何識(shí)別它的?
你知道 —— JSX 只是一種 Facebook 普及的標(biāo)記語(yǔ)法,受益于 Babel/TSC 這些工具 —— 我們能夠以一種更令賞心悅目的方式書寫 React.createElement
調(diào)用。
為什么我會(huì)問(wèn)這個(gè)問(wèn)題?我想知道你是否理解 JSX 的技術(shù)原理以及隨之而來(lái)的限制:為什么甚至在我們的代碼并沒(méi)有使用 React
的情況下,也需要在文件頂部 import React from 'react'
;為什么組件不能直接返回多個(gè)元素。
加分題:為什么 JSX 中的組件名要以大寫字母開頭?
能回答出 React 如何知道要渲染的是組件還是 HTML 元素就夠了。
額外加分點(diǎn):此規(guī)則有很多例外。例如:把一個(gè)組件賦給 this.component
并且寫 <this.component />
也會(huì)起作用。
在 React 中你可以聲明的兩種主要組件類型是什么以及使用時(shí)怎樣在兩者間選擇?
一些人會(huì)認(rèn)為這道題是關(guān)于展示組件和容器組件的,但實(shí)際上是關(guān)于 React.Component
和函數(shù)組件。
恰當(dāng)?shù)幕卮饝?yīng)該提及生命周期函數(shù)和組件狀態(tài)。
由于我們提到了生命周期 —— 你能跟我講一遍掛載狀態(tài)組件的生命周期嗎?哪些函數(shù)按何種順序被調(diào)用?你會(huì)把向 API 的數(shù)據(jù)請(qǐng)求放在哪里執(zhí)行?為什么?
好,這個(gè)問(wèn)題有點(diǎn)長(zhǎng)。請(qǐng)隨意把它分成兩個(gè)小問(wèn)題。你現(xiàn)在會(huì)想“但你說(shuō)你不會(huì)問(wèn)關(guān)于生命周期的內(nèi)容啊!”。我不會(huì)問(wèn),我不關(guān)心生命周期。我關(guān)心的其實(shí)是最近幾個(gè)月生命周期發(fā)生的變化。
如果回答包含 componentWillMount
,你可以假設(shè)此人一直在使用舊版本的 React,或者學(xué)了一些過(guò)時(shí)的教程。兩種情況都會(huì)引起一些擔(dān)憂。getDerivedStateFromProps
才是你在尋找的答案。
額外加分點(diǎn):提到在服務(wù)端上處理方式不同。
關(guān)于數(shù)據(jù)獲取的問(wèn)題也是如此 ——?componentDidMount
是你想要/聽到的之一。
加分題:為什么用 componentDidMount
而不是 constructor
?
你希望聽到的兩個(gè)原因會(huì)是:“在渲染發(fā)生之前數(shù)據(jù)不會(huì)存在” —— 雖然不是主要原因,但它向您顯示該人員了解組件的處理方式; “在 React Fiber 中使用新的異步渲染……” —— 有人一直在努力學(xué)習(xí)。
我們剛才提到通過(guò) API 獲取數(shù)據(jù) —— 你是如何保證在組件重新掛載之后不會(huì)重新獲取數(shù)據(jù)?
我們假設(shè)不存在“緩存失效”。這個(gè)點(diǎn)和 React 關(guān)聯(lián)性并不大,不過(guò)如果回答限制在 React 范圍內(nèi),也是不錯(cuò)的 一 也許他使用的 GraphQL 的方法對(duì)你來(lái)說(shuō)過(guò)于繁重?
我問(wèn)這個(gè)問(wèn)題的目的,是考察候選人是否理解在應(yīng)用中 UI 需要與其他層解耦的理念。可以提及一個(gè) React 架構(gòu)外部的 API。
你能解釋下“狀態(tài)提升”理念嗎?
好,我確實(shí)問(wèn)了一些典型的 React 問(wèn)題。不過(guò)這一個(gè)是至關(guān)重要的,允許你給候選人一些放松空間。
首選答案是“它允許你在兄弟組件間傳遞數(shù)據(jù)”或“它允許你擁有更多純展示組件,更易復(fù)用”。在這里也許會(huì)提到 Redux,不過(guò)這可能也是一件壞事,因?yàn)樗硎竞蜻x人只是跟隨社區(qū)推薦的任何東西,而不理解他為什么需要它。
加分題:如果不能在組件間傳遞數(shù)據(jù),你怎樣給多級(jí)組件傳遞數(shù)據(jù)? 自從 React 16.3 開始,Context 已經(jīng)成為主流 —— 它之前就已經(jīng)存在了,不過(guò)文檔是缺失的(有意為之)。如果能在解釋出 Context 的工作方式(同時(shí)能表現(xiàn)出知道 function-as-child 模式)會(huì)是加分項(xiàng)。
如果這里能提到 Redux 或 MobX 也很好。
React 生態(tài)
開發(fā) React 應(yīng)用只是流程的一部分 —— 還有更多的要做:調(diào)試、測(cè)試和文檔。
你是怎樣調(diào)試 React 代碼問(wèn)題的,你用哪些工具?你會(huì)怎樣調(diào)查組件沒(méi)有重新渲染的問(wèn)題?
每個(gè)人都應(yīng)該熟悉像 linter(eslint,jslint)和調(diào)試工具(React Developer Tools)這些基本工具。
使用 RDT 來(lái)調(diào)試問(wèn)題并通過(guò)檢查組件 state/props 是否正確是一個(gè)不錯(cuò)的答案,如果能提到用 Developer Tools 來(lái)打斷點(diǎn)也是很好的回答。
你用過(guò)哪些測(cè)試工具來(lái)寫 unit/E2E 測(cè)試?快照測(cè)試是什么及它的好處?
在大多數(shù)情況下測(cè)試是“不可避免的麻煩”,但它們又是我們所需要的。有很多優(yōu)秀的答案:karma、mocha、jasmin、jest、cypres、selenium、enzyme、react-test-library 等等。最糟糕的事是候選人回答“上一家公司我們不做單元測(cè)試,只有人工測(cè)試”。
快照測(cè)試部分的回答依賴于你的項(xiàng)目里用了什么;如果你覺得它不是很有用就不要問(wèn)及。但是如果覺得有用 —— 答案就是“用于 HTML + CSS 生成的 UI 層的便捷回歸測(cè)試”。
小型的代碼挑戰(zhàn)
如果有可能,我也會(huì)讓候選人來(lái)做一些小型的代碼挑戰(zhàn),解決/解釋它們不應(yīng)該花費(fèi)超過(guò)一兩分鐘,例如:
/**
* 這個(gè)例子有什么問(wèn)題,要如何修改或改進(jìn)這個(gè)組件?
*/
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
name: this.props.name || 'Anonymous'
}
}
render() {
return (
<p>Hello {this.state.name}</p>
);
}
}
有很多方式來(lái)解決它:移除 state 并使用 props,實(shí)現(xiàn) getDerivedStateFromProps
或者更好的方式是把該組件變?yōu)楹瘮?shù)組件。
/**
* 這幾個(gè)向組件傳遞函數(shù)的方式,你能解釋它們的不同嗎?
*
* 當(dāng)你點(diǎn)擊每個(gè)按鈕會(huì)發(fā)生什么?
*/
class App extends React.Component {
constructor() {
super();
this.name = 'MyComponent';
this.handleClick2 = this.handleClick1.bind(this);
}
handleClick1() {
alert(this.name);
}
handleClick3 = () => alert(this.name);
render() {
return (
<div>
<button onClick={this.handleClick1()}>click 1</button> //MyComponent剛開始就只執(zhí)行
<button onClick={this.handleClick1}>click 2</button>//空
<button onClick={this.handleClick2}>click 3</button>//MyComponent
<button onClick={this.handleClick3}>click 4</button>//MyComponent
</div>
);
}
}
這道題要稍微費(fèi)點(diǎn)功夫,因?yàn)榇a比較多。如果候選人回答正確緊接著問(wèn)“為什么?”。為什么 click 2
這會(huì)以這種方式運(yùn)行?
這個(gè)不是 React 問(wèn)題,如果有人的回答以“因?yàn)樵?React 中……”開始,這說(shuō)明他們沒(méi)有真正理解 JS 事件循環(huán)機(jī)制。
/**
* 這個(gè)組件有什么問(wèn)題。為什么?要如何解決呢?
*/
class App extends React.Component {
state = { search: '' }
handleChange = event => {
/**
* 這是“防抖”函數(shù)的簡(jiǎn)單實(shí)現(xiàn),它會(huì)以隊(duì)列的方式在 250 ms 內(nèi)調(diào)用
* 表達(dá)式并取消所有掛起的隊(duì)列表達(dá)式。以這種方式我們可以在用戶停止輸
* 入時(shí)延遲 250 ms 來(lái)調(diào)用表達(dá)式。
*/
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.setState({
search: event.target.value
})
}, 250);
}
render() {
return (
<div>
<input type="text" onChange={this.handleChange} />
{this.state.search ? <p>Search for: {this.state.search}</p> : null}
</div>
)
}
}
好,這道題就需要一些解釋了。在防抖函數(shù)中并沒(méi)有錯(cuò)誤。那么應(yīng)用會(huì)按期望方式運(yùn)行嗎?它會(huì)在用戶停止輸入的 250 ms 之后更新并且渲染字符串“Search for: …”嗎?
這里的問(wèn)題是在 React 中 event
是一個(gè) SyntheticEvent
,如果和它的交互被延遲了(例如:通過(guò) setTimeout
),事件會(huì)被清除并且 .target.value
引用不會(huì)再有效。
額外加分點(diǎn):候選人要能解釋出為什么。
技術(shù)問(wèn)題環(huán)節(jié)完畢
這應(yīng)該足夠你了解候選人的技能了。不過(guò)你還要為開放問(wèn)答留一些時(shí)間。
你在過(guò)去的項(xiàng)目里遇到的最大問(wèn)題是什么?你最大的成就?
這就回到第一個(gè)問(wèn)題了 —— 答案可能因開發(fā)人員以及職位而異。初級(jí)開發(fā)人員會(huì)說(shuō)他最大的問(wèn)題是在一個(gè)復(fù)雜的過(guò)程中報(bào)錯(cuò),但他可以征服它。尋找更高級(jí)職位的人將解釋他如何優(yōu)化應(yīng)用程序性能,而帶領(lǐng)團(tuán)隊(duì)的人會(huì)解釋他如何通過(guò)結(jié)對(duì)編程提高速度。
如果你有無(wú)限的時(shí)間預(yù)算并讓你解決/提升/改變你最后一個(gè)項(xiàng)目里的一項(xiàng)東西,你會(huì)選什么,以及為什么選它?
而別的開放問(wèn)題則要看你要在候選人身上尋找什么。他會(huì)嘗試用 MobX 替換 Redux 嗎?改進(jìn)測(cè)試設(shè)置?寫出更好的文檔?
對(duì)調(diào)表格和反饋
現(xiàn)在是時(shí)候改變角色了。你可能已經(jīng)對(duì)候選人的技能和成長(zhǎng)潛力有了充分的了解。讓他問(wèn)些問(wèn)題 —— 這不僅可以讓他更多地了解公司和產(chǎn)品,他問(wèn)的問(wèn)題可能會(huì)給你一些關(guān)于他想要成長(zhǎng)方向的指示。
Carl Vitullo 寫過(guò)一些關(guān)于要問(wèn)你的潛在雇主的問(wèn)題的好文章,我會(huì)推薦給你 —— 準(zhǔn)備好回答他們,除非因?yàn)楸C軈f(xié)議或別的需要讓你不能問(wèn)某些特定問(wèn)題:
入職和工作場(chǎng)所
發(fā)展和緊急情況
成長(zhǎng)
給予反饋
如果候選人在某些問(wèn)題上表現(xiàn)不佳或者回答錯(cuò)誤(或者與你預(yù)期不同)—— 這時(shí)你可能希望澄清這些問(wèn)題。不要讓它聽起來(lái)像是在青睞此人,只要解釋你注意到的問(wèn)題 —— 提供解決方案和一些他可以用來(lái)改善自己的資源。
如果招聘過(guò)程的其余部分取決于您,請(qǐng)告訴他們您將在 X 天內(nèi)回復(fù)他們,如果沒(méi)有,請(qǐng)告訴他們你們公司的某個(gè)人會(huì)這樣做。如果您知道該過(guò)程需要超過(guò) 2-3 天,請(qǐng)告訴他們。現(xiàn)在 IT 是一個(gè)很大的市場(chǎng),候選人可能已經(jīng)進(jìn)行了多次面試 —— 他可能會(huì)接受另一個(gè) offer 而不會(huì)等你的反饋。
不要輕視候選人 —— 這其實(shí)是人們?cè)谏缃幻襟w上經(jīng)常抱怨的。
本篇文章中表達(dá)的是我自己的觀點(diǎn),不能代表我過(guò)去或現(xiàn)任雇主,客戶或合作者的意見。
如果發(fā)現(xiàn)譯文存在錯(cuò)誤或其他需要改進(jìn)的地方,歡迎到 掘金翻譯計(jì)劃 對(duì)譯文進(jìn)行修改并 PR,也可獲得相應(yīng)獎(jiǎng)勵(lì)積分。文章開頭的 本文永久鏈接 即為本文在 GitHub 上的 MarkDown 鏈接。