:小紅書2020校招筆試題卷二核心考點(diǎn)拆解)
小紅書2020校招前端筆試題卷二在當(dāng)年的校招群里流傳度非常高。我記得好幾個學(xué)弟學(xué)妹輪番來問我同一個問題這套卷子該怎么準(zhǔn)備我翻完流傳出來的題目版本之后最大的感受是它沒有一句廢話——閉包、this指向、事件循環(huán)、跨域、渲染機(jī)制、手寫代碼幾乎把前端基礎(chǔ)里最容易出錯的硬骨頭都點(diǎn)名了一遍。哪怕現(xiàn)在已經(jīng)不是2020年前端技術(shù)棧一直在變但這套卷對準(zhǔn)備校招、跳槽和想系統(tǒng)性自查基礎(chǔ)的人來說依然是一份很好的體檢清單。它能幫你快速找到那些“我以為是會的其實(shí)根本不懂”的地方。如果你正在準(zhǔn)備前端崗位的筆試面試或者工作兩三年后感覺自己基礎(chǔ)不牢都可以拿這套題做一次自測。下面我會按模塊拆解卷子里最容易考、也最容易丟分的幾個方向把核心原理、答題思路和當(dāng)時同學(xué)踩過的坑一起說清楚。1. 試卷結(jié)構(gòu)與考察思路拆解1.1 卷二在整輪筆試中的定位小紅書2020校招前端筆試實(shí)際投放的不止一套卷子卷二屬于典型的基礎(chǔ)綜合卷邏輯是在簡歷篩選之后、面試之前先用機(jī)器或者人工快速篩一遍候選人的下限。這類卷子不會故意出偏題怪題但普遍題量大、覆蓋廣限時內(nèi)想拿高分并不輕松。當(dāng)時我拿到流傳出來的版本印象最深的是題目層級很分明大致可以分成三類選擇題負(fù)責(zé)考察概念辨析和語法易錯點(diǎn)包括單選和多選簡答題負(fù)責(zé)考察理解深度比如讓你解釋某個機(jī)制或者某個方案編碼題則直接要求手寫實(shí)現(xiàn)比如防抖節(jié)流、數(shù)組去重、深淺拷貝等。選擇題測的是“知不知道”簡答題測的是“理不理解”編碼題測的是“能不能寫出來”。這三個層次層層遞進(jìn)比單純刷算法題更能反映一個前端候選人的真實(shí)水平。所以如果你只是在???、LeetCode上狂刷題忽視了對知識體系的理解卷二這類試卷很容易讓你原形畢露。1.2 校招筆試真正想看到的答案長什么樣很多同學(xué)容易陷入一個誤區(qū)簡答題寫得越多越好最好把所有相關(guān)名詞都堆上去。其實(shí)打分的人更想看到“先說什么、后說什么、為什么這樣設(shè)計(jì)”的邏輯鏈條。舉一個高頻簡答題為例“跨域有哪些解決方式”。如果只是列出來JSONP、CORS、postMessage、代理轉(zhuǎn)發(fā)那只能算及格。真正能拿高分的答法是先點(diǎn)出跨域的本質(zhì)是同源策略對“協(xié)議、域名、端口”的限制再分別說明每種方案適合什么場景最后給出當(dāng)前項(xiàng)目里的推薦做法和注意事項(xiàng)。卷二里的簡答題占比不低答法不同分?jǐn)?shù)差距會很大。我建議平時復(fù)習(xí)時不要只背面經(jīng)可以試著把每個知識點(diǎn)當(dāng)成一個“小報告”先定義、再解釋原理、最后給場景這樣無論題目怎么變形你都能答到點(diǎn)子上。1.3 考點(diǎn)分布速查表考察模塊常見題型推薦優(yōu)先級JavaScript 基礎(chǔ)選擇、簡答、編碼極高瀏覽器與網(wǎng)絡(luò)選擇、簡答高CSS 與布局選擇、編碼高Vue/React 框架選擇、簡答中高手寫代碼編碼極高這個優(yōu)先級參考了近幾年的校招筆試題和面經(jīng)統(tǒng)計(jì)不一定完全對應(yīng)某一次考試但大方向是穩(wěn)定的??忌鷱?fù)習(xí)時應(yīng)該優(yōu)先保證JavaScript和手寫代碼的正確率因?yàn)樗鼈儙缀趺刻拙矶紩霈F(xiàn)而且一旦寫錯基本沒有蒙對的概率。2. JavaScript 基礎(chǔ)閉包、作用域與this指向2.1 閉包經(jīng)典考法從輸出結(jié)果到修復(fù)代碼卷二在JavaScript部分最常出現(xiàn)的是閉包相關(guān)題目。閉包的經(jīng)典考法有兩種一種是問輸出結(jié)果另一種是讓你修復(fù)代碼中的問題。問輸出結(jié)果幾乎是繞不開這個場景的for (var i 0; i 5; i) { setTimeout(function() { console.log(i); }, 1000); }這段代碼最終不是打印0、1、2、3、4而是一秒后連續(xù)打印五個5。原因有兩層第一var聲明的i是函數(shù)級作用域循環(huán)體里外共用同一個變量第二setTimeout的回調(diào)是在循環(huán)完全結(jié)束之后才執(zhí)行的此時i已經(jīng)自增到了5。只要抓住“變量作用域 異步執(zhí)行時機(jī)”這條主鏈類似題目基本不會再錯。考試?yán)镞€會繼續(xù)追問改成let i為什么就對了因?yàn)閘et在每次迭代中都會創(chuàng)建一次新的詞法環(huán)境綁定閉包捕獲的是當(dāng)前這一次的i而不是循環(huán)結(jié)束之后的最終值。另一個常見修法是用立即執(zhí)行函數(shù)把i作為參數(shù)傳進(jìn)新函數(shù)作用域for (var i 0; i 5; i) { (function(j) { setTimeout(function() { console.log(j); }, 1000); })(i); }如果考簡答大概率會讓你解釋閉包是什么、為什么存在、有什么坑、怎么解決。要答得漂亮最好講清楚三點(diǎn)閉包能在函數(shù)外部訪問到其內(nèi)部作用域的變量它能讓變量長期駐留所以常被用來封裝私有狀態(tài)但如果使用不當(dāng)也可能造成內(nèi)存泄漏或循環(huán)引用。2.2 this指向不要背口訣要會看調(diào)用方式this指向問題是前端筆試的常青樹卷二里有個很經(jīng)典的嵌套函數(shù)版本var name window; var obj { name: obj, getName: function() { return function() { return this.name; }; } }; console.log(obj.getName()());這段代碼最終打印的是window而不是obj。原因是函數(shù)調(diào)用時this指向取決于調(diào)用者。嵌套的那個匿名函數(shù)是獨(dú)立調(diào)用的沒有對象前綴所以this指向全局對象瀏覽器環(huán)境就是window。這類題目經(jīng)常搭配三種修法來考把外層this保存到一個變量里比如var self this改用箭頭函數(shù)因?yàn)榧^函數(shù)沒有自己的this它從定義時的外層作用域繼承或者在返回函數(shù)時用bind(this)。很多同學(xué)喜歡死背“誰調(diào)用就指向誰”的口訣但它的例外實(shí)在太多。我建議用更可靠的判定方法也就是看函數(shù)的調(diào)用表達(dá)式屬于哪一種fn()直接調(diào)用非嚴(yán)格模式下this指向全局對象。obj.fn()方法調(diào)用this指向obj。new fn()構(gòu)造調(diào)用this指向新創(chuàng)建的對象。fn.call(obj)/fn.apply(obj)/fn.bind(obj)顯式綁定this指向指定的obj。把這四種情況分清楚再遇到任何this題都能慢慢推出來。卷二里還常把this和原型鏈結(jié)合出一道輸出題所以先復(fù)習(xí)好調(diào)用方式后面再遇到更復(fù)雜的場景也不容易翻車。2.3 作用域提升與塊級作用域最容易被忽略的送分題除了閉包和this作用域提升也是一道常見的選擇題。典型的題目是console.log(a); var a 1;控制臺輸出的是undefined而不是報錯。原因在于var聲明會被提升到當(dāng)前作用域頂部但賦值并沒有被提升所以執(zhí)行到console.log(a)時a已經(jīng)存在值卻是undefined。這里需要注意如果換成let a控制臺就會直接報錯因?yàn)閘et存在暫時性死區(qū)在聲明之前訪問變量是不允許的。這些知識點(diǎn)單獨(dú)拎出來都不難但在限時筆試的高壓環(huán)境下很多同學(xué)會憑第一印象選出錯誤答案。我自己的習(xí)慣是遇到這類題先在草稿紙上把“聲明提升、賦值執(zhí)行、作用域鏈查找”三個過程畫出來順序捋清楚再選正確率會高很多。3. 瀏覽器與網(wǎng)絡(luò)從渲染原理到跨域方案3.1 渲染流程、重排重繪與性能優(yōu)化瀏覽器原理中渲染流程絕對是高頻考點(diǎn)。簡化的過程是HTML解析成DOM樹CSS解析成CSSOM樹兩者結(jié)合生成渲染樹然后計(jì)算布局、繪制合成。這個流程本身不難背難的是把它和相關(guān)問題串起來。比如卷子里可能問“為什么操作DOM會影響性能”答案不是簡單說“會重排重繪”而是要說明任何改變DOM大小、位置、結(jié)構(gòu)的行為都可能觸發(fā)重新布局而布局計(jì)算會阻塞渲染線程所以頻繁操作DOM累積下來就會非??D。更深入的追問可能是“如何減少重排”。比較靠譜的答案包括批量修改DOM可以用documentFragment先積攢再一并插入用CSS類一次性替換多個樣式而不是逐條修改內(nèi)聯(lián)樣式對動畫元素使用transform或opacity讓它獨(dú)立成合成層減少對主線程布局的觸發(fā)。這些實(shí)戰(zhàn)技巧在筆試?yán)锖芗臃忠驗(yàn)殚喚砣艘谎劬湍芸闯瞿闶遣皇钦娴奶幚磉^性能問題。3.2 跨域的源頭與主流解決方式跨域在卷二里出現(xiàn)頻率很高很多考生能列舉JSONP、CORS、postMessage但一到簡答題就說不清為什么會有跨域。它的根源是瀏覽器的同源策略目的是防止一個源隨意讀取另一個源的數(shù)據(jù)。同源要求協(xié)議、域名、端口三者完全一致任何一項(xiàng)不同都算跨域。理解了這個前提再去區(qū)分方案就清晰很多JSONP利用的是script標(biāo)簽不受同源限制的特性只能發(fā)GET請求適合接口比較簡單的老系統(tǒng)。CORS是通過后端在響應(yīng)頭里聲明允許的源這是現(xiàn)代Web應(yīng)用的標(biāo)準(zhǔn)方案。需要區(qū)分簡單請求和非簡單請求非簡單請求會先觸發(fā)OPTIONS預(yù)檢。代理轉(zhuǎn)發(fā)適合開發(fā)環(huán)境和同源部署場景讓前端請求打到同源后端再由后端轉(zhuǎn)發(fā)到目標(biāo)接口這樣瀏覽器層面就不存在跨域問題。選擇題里常見的坑是混淆“跨域能不能發(fā)請求”和“跨域能不能讀到響應(yīng)”。實(shí)際上非簡單請求會先發(fā)出預(yù)檢請求真正的報錯往往發(fā)生在響應(yīng)被攔截階段而不是請求沒有發(fā)出去。只要把這一點(diǎn)理解到位跨域選擇題的準(zhǔn)確率能提升不少。3.3 事件循環(huán)與微任務(wù)宏任務(wù)別在嵌套里算錯順序?yàn)g覽器部分大概率會有一道事件循環(huán)題。核心知識點(diǎn)是JavaScript是單線程的同步代碼先執(zhí)行遇到異步任務(wù)會交給瀏覽器其他線程處理異步任務(wù)完成后回調(diào)會被放進(jìn)任務(wù)隊(duì)列在執(zhí)行棧清空后瀏覽器先處理微任務(wù)隊(duì)列再取出一個宏任務(wù)執(zhí)行循環(huán)往復(fù)。經(jīng)典的輸出題形如console.log(1); Promise.resolve().then(() console.log(2)); setTimeout(() console.log(3), 0); console.log(4);結(jié)果是1、4、2、3。原因就是Promise的then屬于微任務(wù)setTimeout的回調(diào)屬于宏任務(wù)微任務(wù)會在下一個宏任務(wù)之前先執(zhí)行。如果再混入async/await會更容易算錯async function test() { console.log(1); await Promise.resolve(); console.log(2); } console.log(3); test(); console.log(4);這里的輸出順序是3、1、4、2。注意看調(diào)用test()后函數(shù)體里的console.log(1)是同步執(zhí)行的遇到await才把后續(xù)代碼異步化所以主線程繼續(xù)往下執(zhí)行了console.log(4)然后才輪到微任務(wù)里的console.log(2)。我的笨辦法是拿到題目先標(biāo)記同步代碼再把宏任務(wù)和微任務(wù)分別列成小隊(duì)列最后按順序執(zhí)行基本不會錯。3.4 HTTP緩存與存儲選擇題里的隱形考點(diǎn)除了渲染和跨域?yàn)g覽器部分還經(jīng)常穿插HTTP緩存和存儲相關(guān)的選擇題。緩存方面要能清晰區(qū)分強(qiáng)緩存和協(xié)商緩存強(qiáng)緩存直接通過Cache-Control或Expires判斷緩存是否有效有效期內(nèi)不會發(fā)請求協(xié)商緩存則需要帶上Last-Modified或ETag去服務(wù)器驗(yàn)證服務(wù)器返回304則繼續(xù)用緩存。存儲方面cookie、localStorage、sessionStorage、IndexedDB四者的區(qū)別也是高頻題考試時經(jīng)常拿“容量限制”“是否隨請求發(fā)送”“是否自動過期”這幾個維度做混淆選項(xiàng)。這些知識看起來零散實(shí)際上背清楚一張對比表就能穩(wěn)穩(wěn)拿到分。4. CSS與布局BFC、flex與經(jīng)典布局實(shí)戰(zhàn)4.1 BFC一個獨(dú)立渲染小世界CSS部分卷二對BFC的偏愛非常明顯。BFC全稱是塊級格式化上下文你可以把它理解為一個獨(dú)立的渲染小世界在這個小世界里元素的布局不會影響外部外部也不會影響它內(nèi)部。哪些情況會觸發(fā)BFC浮動、絕對定位、inline-block、overflow不為visible的塊級元素、flex容器等都會觸發(fā)。卷子里??嫉念}目是“如何清除浮動”答案里一定會提到overflow: hidden。但你要能解釋它背后的原理給父容器創(chuàng)建了一個BFC讓浮動元素也參與父容器的高度計(jì)算從而把子元素“包”起來。另一個高頻考點(diǎn)是“如何防止margin合并”同樣可以通過在父容器上創(chuàng)建BFC讓相鄰元素的垂直margin被隔離在獨(dú)立的上下文中。這里我把容易混淆的觸發(fā)條件整理成一個清單float不是none。position是absolute或fixed。display是inline-block、table-cell、flex或grid。overflow不是visible??荚嚂r問到某個元素是否創(chuàng)建了BFC直接按這幾個條件套就能判斷。4.2 盒模型一個必拿的基礎(chǔ)分盒模型雖然簡單但錯的人非常多。標(biāo)準(zhǔn)盒模型里width只包含內(nèi)容區(qū)而IE盒模型box-sizing: border-box里width包含了內(nèi)容、padding和border。卷二選擇題特別喜歡給一組場景比如“給一個元素設(shè)置width: 100px; padding: 20px; border: 5px標(biāo)準(zhǔn)模型里的真實(shí)占位寬度是多少”很多人一緊張就算錯。其實(shí)答案很簡單標(biāo)準(zhǔn)模型下真實(shí)占位寬度是100 20*2 5*2 150px如果是border-box真實(shí)占位寬度就是100px。這類題沒有任何難度只要在讀題時先確認(rèn)一下是否設(shè)置了box-sizing就能穩(wěn)拿分。4.3 垂直居中與兩欄布局高頻編碼實(shí)操布局題也是卷二的高頻題尤其是“垂直居中”和“兩欄/三欄布局”。垂直居中看似簡單但不同場景對應(yīng)不同最佳解。父容器寬高未知子元素尺寸也未知最推薦flex方案.parent { display: flex; justify-content: center; align-items: center; }如果要求兼容老瀏覽器可以用絕對定位加負(fù)margin但前提是子元素尺寸已知。還有基于transform: translate(-50%, -50%)的方案它的百分比是相對于元素自身尺寸計(jì)算的所以不需要知道具體寬高這也是它適合當(dāng)作通用方案的原因。兩欄布局里經(jīng)典做法是左側(cè)固定寬度右側(cè)自適應(yīng)。用flex實(shí)現(xiàn)很簡單左邊f(xié)lex: 0 0 240px右邊f(xié)lex: 1。三欄布局則??际ケ季趾碗p飛翼布局目的是讓中間欄先渲染再通過負(fù)margin或padding把兩側(cè)讓出來。要理解這類布局核心是吃透“負(fù)margin會改變元素在文檔流中的占位位置”剩下就是組合游戲。死記代碼很容易忘但把原理想明白之后任何變體都能應(yīng)對。5. 框架知識Vue/React 核心機(jī)制5.1 Vue的響應(yīng)式原理從Object.defineProperty到Proxy2020年的筆試題框架部分默認(rèn)你已經(jīng)會Vue或React。Vue高頻題是“響應(yīng)式原理是什么”要答清楚它不是魔術(shù)而是數(shù)據(jù)劫持加發(fā)布訂閱。2.x版本用Object.defineProperty遍歷對象屬性并定義getter/setter頁面讀取數(shù)據(jù)時收集依賴數(shù)據(jù)變化時派發(fā)通知觸發(fā)重新渲染。3.0版本改成用Proxy它能攔截更多操作比如屬性的新增和刪除同時性能更好。卷子里如果出這類題很可能搭配一個實(shí)操問題給Vue 2的數(shù)組新增元素為什么頁面不更新原因在于Object.defineProperty無法攔截通過索引設(shè)置新值這種操作所以需要借助$set或者重寫過的數(shù)組方法來觸發(fā)更新。很多同學(xué)只背了“數(shù)組要用$set”這個結(jié)論卻不知道背后的邊界在哪里。我的建議是復(fù)習(xí)時親手寫一個小例子在Vue 2和Vue 3里分別改數(shù)組親眼看看輸出差異這比背十篇面經(jīng)都更牢固。5.2 虛擬DOM與diff為什么key不能亂用indexReact和Vue都會聊到虛擬DOM。它到底是什么可以理解為用JavaScript對象來描述DOM結(jié)構(gòu)一次界面渲染對應(yīng)一棵虛擬節(jié)點(diǎn)樹。為什么需要它因?yàn)橹苯硬僮髡鎸?shí)DOM成本高而操作JavaScript對象是純內(nèi)存操作非??煸偌由蟙iff算法能找出前后兩棵樹的差異只更新真正變化的部分整體性能體驗(yàn)更好。卷子里??嫉牟⒉皇莇iff的每行代碼而是它的基本策略同層比較、tag不同直接替換、key用于盡可能復(fù)用節(jié)點(diǎn)。關(guān)于key高頻追問是“為什么列表渲染時不能濫用index作為key”。因?yàn)樵跀?shù)組頭部插入或刪除元素時index會整體變化導(dǎo)致原本被復(fù)用的節(jié)點(diǎn)錯亂輕則渲染狀態(tài)不對重則出現(xiàn)難以排查的交互問題。這個場景不需要高深技術(shù)用一個todo列表自己操作一遍就能理解。5.3 生命周期與組件通信框架部分的簡答題還經(jīng)常圍繞生命周期出題。Vue里最常見的追問是created和mounted的區(qū)別created時數(shù)據(jù)已經(jīng)初始化但DOM還沒掛載適合在這里發(fā)請求或初始化數(shù)據(jù)mounted時DOM已掛載適合做依賴真實(shí)DOM的操作。React那邊則常問函數(shù)組件里useEffect如何對應(yīng)類組件的生命周期以及為什么要清理副作用。組件通信也是必考方向Vue里的props/emit、provide/inject、VuexReact里的狀態(tài)提升、Context、Redux都要能說出各自的適用場景。答這類題不需要長篇大論核心點(diǎn)出“單向數(shù)據(jù)流”和“狀態(tài)管理解決什么問題”就夠了。6. 編碼題實(shí)戰(zhàn)手寫實(shí)現(xiàn)與算法基礎(chǔ)6.1 手寫防抖與節(jié)流三個細(xì)節(jié)決定分?jǐn)?shù)編碼題部分手寫防抖和節(jié)流幾乎是保留節(jié)目。防抖的核心思想是事件觸發(fā)后等待一段時間再執(zhí)行如果在這個等待時間里再次觸發(fā)就重新計(jì)時。節(jié)流的核心思想是在一段時間內(nèi)只允許執(zhí)行一次。它們分別適合什么場景輸入框?qū)崟r搜索適合防抖因?yàn)橛脩暨B續(xù)輸入時不需要頻繁請求滾動監(jiān)聽和按鈕防連擊適合節(jié)流因?yàn)樾枰WC一定的執(zhí)行頻率。防抖的經(jīng)典實(shí)現(xiàn)是這樣的function debounce(fn, delay) { let timer null; return function(...args) { const context this; clearTimeout(timer); timer setTimeout(() { fn.apply(context, args); }, delay); }; }這里有三個細(xì)節(jié)很容易丟分。第一要保留this指向所以用了apply第二要透傳參數(shù)所以用了...args第三是否能說出“什么是立即執(zhí)行版本、什么場景需要立即執(zhí)行”這決定了你是背代碼還是真掌握了原理。節(jié)流的實(shí)現(xiàn)也有時間戳和定時器兩種常見版本考試時能說出兩者區(qū)別第一次是否立即執(zhí)行、最后一次是否補(bǔ)執(zhí)行會非常加分。6.2 數(shù)組去重與扁平化從一行API到進(jìn)階追問數(shù)組去重是編碼題的另一個??妥詈唵蔚陌姹臼莄onst unique arr Array.from(new Set(arr));一行代碼就能解決。但你能講講它的局限嗎Set去重使用類似全等的規(guī)則對基本類型沒問題對對象類型則只能比較引用所以兩個內(nèi)容相同但引用不同的對象都會被保留。如果要求對象數(shù)組按某個字段去重就需要用Map來記錄。再往下考數(shù)組扁平化也有多層考法基礎(chǔ)版是直接調(diào)用flat()方法進(jìn)階版是手寫遞歸再進(jìn)一層是支持指定深度。這些題目表面看是考API實(shí)際是考你能否在特定限制下寫出清晰可靠的代碼。6.3 深拷貝、手寫call/apply/bind卷二的手寫題還可能涉及深拷貝和手寫call/apply/bind。深拷貝的面試題很考驗(yàn)功底基礎(chǔ)版是遞歸遍歷屬性進(jìn)階版需要處理數(shù)組、Date、RegExp等特殊類型還要用WeakMap緩存引用避免循環(huán)引用導(dǎo)致死循環(huán)。手寫call的思路則是利用臨時屬性改變this指向Function.prototype.myCall function(context, ...args) { context context || window; const fn Symbol(fn); context[fn] this; const result context[fn](...args); delete context[fn]; return result; };這里用Symbol是為了避免覆蓋context上已有的同名屬性。其實(shí)這類手寫題對日常業(yè)務(wù)開發(fā)幫助不大但它在筆試?yán)锬芸焖贆z驗(yàn)一個人對JavaScript底層機(jī)制的理解程度。準(zhǔn)備方式是理解思路后親手敲三遍而不是把代碼背下來。6.4 算法題策略別輸在“看得懂卻寫不出”算法題在卷二里的難度一般不會達(dá)到LeetCode困難題更多是鏈表反轉(zhuǎn)、二叉樹層序遍歷、最長不重復(fù)子串這類中等偏下題目。很多同學(xué)的問題不是沒有思路而是沒有把邊界條件、空值處理、循環(huán)終止條件寫完整。我建議刷題時不要只看題解要動筆把主路徑寫出來再補(bǔ)邊界。筆試時間有限遇到算法題先花兩分鐘確認(rèn)輸入輸出再寫一個能跑通的主路徑最后補(bǔ)邊界這個順序比追求最優(yōu)解更實(shí)際。7. 常見問題與排查技巧實(shí)錄7.1 考生最容易丟分的三個習(xí)慣我翻過不少同學(xué)的筆試復(fù)盤發(fā)現(xiàn)丟分點(diǎn)往往不在知識本身而在表達(dá)和代碼習(xí)慣。第一個壞習(xí)慣是簡答題寫太短只給結(jié)論不給過程比如“跨域用CORS”卻沒有說明場景和限制。第二個壞習(xí)慣是代碼題一上來就封裝各種工具函數(shù)結(jié)果主功能反而沒寫完正確策略是先實(shí)現(xiàn)核心流程保證基本用例通過再考慮封裝擴(kuò)展。第三個壞習(xí)慣是不檢查邊界比如防抖函數(shù)沒有處理this、數(shù)組去重沒有考慮空數(shù)組這些小問題會讓閱卷人對工程素養(yǎng)打個問號。7.2 時間分配與答題順序建議根據(jù)卷二這類基礎(chǔ)綜合卷的題量和難度我的建議是拿到卷子先快速掃一遍全部題目估算每種題型的大概耗時。選擇題不要猶豫太久先按第一直覺選不確定的做標(biāo)記簡答題控制在每題十分鐘以內(nèi)寫出核心邏輯鏈編碼題給足時間最好留出二十分鐘做檢查。做題順序上建議先做自己有把握的模塊把分?jǐn)?shù)先拿到手再回頭啃硬骨頭。筆試往往按總分篩選穩(wěn)拿的分比鉆牛角尖更有價值。7.3 常見問題速查表問題常見原因解決辦法事件循環(huán)輸出順序算錯混淆微任務(wù)與宏任務(wù)先列同步代碼再分別收集兩個隊(duì)列閉包打印全是循環(huán)末值沒理解var作用域與異步時機(jī)改用let或IIFE垂直居中布局失效父容器或子元素尺寸約束不一致確認(rèn)flex三要素檢查子元素是否被壓縮跨域請求報錯忽略預(yù)檢請求或響應(yīng)頭配置分清簡單請求與非簡單請求數(shù)組增刪后列表渲染錯亂key用了index改用業(yè)務(wù)唯一id這張表是我根據(jù)同學(xué)常問的問題整理出來的不一定覆蓋全部但能解決八成筆試現(xiàn)場出現(xiàn)的低級失誤。7.4 手寫題的一個小技巧最后分享一個我自己用過很多次的小技巧手寫題如果一時想不起具體API不要空著。先把函數(shù)簽名寫出來把注釋寫好再用偽代碼表達(dá)思路。閱卷者通常會給“思路正確但實(shí)現(xiàn)有瑕疵”的答案額外同情分。比如防抖你忘了clearTimeout那就寫“清除之前的定時器”這種注釋至少能讓閱卷人知道你的方向是對的。卷面整潔、命名規(guī)范在同等條件下真的能拉開差距。小紅書這套2020年的前端筆試題卷二我后來給身邊準(zhǔn)備跳槽的同事也用過。大家的共同感受是題目不算難但很能暴露基本功。閉包、事件循環(huán)、BFC、跨域這些知識點(diǎn)平時寫業(yè)務(wù)的時候感覺都用不上可一旦被問到才發(fā)現(xiàn)自己只是眼熟而不是掌握。準(zhǔn)備這類筆試最忌諱的就是只看面經(jīng)背答案。我的體會是把每個考點(diǎn)都自己動手驗(yàn)證一遍比如在瀏覽器控制臺跑一遍this指向的代碼看看輸出到底是什么把防抖節(jié)流的調(diào)用方式寫進(jìn)一個真實(shí)的小項(xiàng)目里感受它們在網(wǎng)絡(luò)請求上的區(qū)別。這樣學(xué)一遍比考前突擊三十道題都管用。希望這篇拆解能幫你在下一次筆試?yán)锷俨葞讉€我已經(jīng)替你踩過的坑。