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