當了幾年的伸手黨,最近也準備輸出一些自己的東西。
關於我
首先介紹一下我自己,17 年畢業於一所 211 學校,但是由於大學四年馳騁在召喚師峽谷,畢業時也沒有找到一份大廠的工作,隨便找了一家創業公司簽了三方就去了。好在這家公司也挺給力,我這一呆就是三年,996 當着「全乾工程師」,從前端到服務端,從 JavaScript 到 Java,這幾年下來都積累了一些經驗,不説精通,也算是比較熟悉了。
今年 7 月份的時候,瞅着已經畢業三年,是時候該考慮一下職業生涯的下一站了,開始準備面試的事情。
這裏建議大家,每一份工作度需要慎重考慮,不要頻繁跳槽。文章後面也會給出我的理由和建議。
在職準備了 2 個月的面試,開始試着投了一些簡歷,幸運的是都收到了面試邀請,有的公司也拿到了 offer。也嘗試投了幾家大廠,阿里、字節、快手目前還在流程中。
也已經向 TL 提了離職,最近在工作交接,事情比較少,寫個文章記錄一下最近的經歷。第一次在掘金寫文章,希望能有人看。
工作三年
一晃時間就過去了三年,從畢業時候對前端一竅不通到如今在公司獨當一面,也算是成長了挺多。嗯,畢業三年的我有4年經驗(手動狗頭)。
記個流水賬吧,大家能夠比較直觀地感受到我畢業三年以來每個階段做了什麼事:
- 2017年1月左右。比較早搞定了畢業設計,開始早開始籌備找工作的事。由於是計算機專業畢業,第一想法當然還是找編程相關的工作,就開始瞭解目前的前端工程師、後端工程師都在做什麼,找了幾個大廠的 JD 就開始研究,並且聽同學説現在牛客上招聘和麪經比較多,就去翻了翻牛客。看了牛客之後,TM 被打擊了。。。這面經也太難了吧,真的是「面試造火箭」
- 2017年1月底過年。過年期間回老家同學聚會,剛好也有朋友是計算機專業,建議我可以自學一下前端,找一份前端開發的工作。大二大三的時候幫學長做項目也寫過一些前端的代碼,想想也挺有趣的,也不糾結了就找前端吧
- 2017年4月左右。體系化地學習了一下前端相關的知識,發現不對勁,沒有實習過的我對於整體的工程經驗太欠缺了,而且光是寫 Demo 根本無法深入學習,但是由於時間比較少需要看的內容比較多,又只能淺嘗則止
- 2017年5月。投了幾份簡歷,面了幾家公司,offer 有,但也都是小公司,對,就是那種只有 20 個人左右的小公司,想想還是放棄了
- 2017年6月。機緣巧合在 V2ex 上了解到一個創業公司,人不多,但是待遇還不錯,就去試了試。面試官很 Nice,聊得挺不錯,雖然我沒有實習經驗也沒關係,他覺得應屆生基礎好,學習能力強就沒問題(? 我信了。。)
- 2017年6月。簽了三方,畢業旅行去了。美滋滋。
- 2017年7月。從學校畢業,進入這家創業公司開始了我的前端生涯
- 2017年7月 - 12月。因為這家創業公司已經有一定規模了,除我之外還有 3 個前端,所以我剛來之後活還比較輕,主要就是寫一些無關經驗的後台頁面和 toC 的移動端頁面,主要技術棧是 Vue。Vue 也是我來了公司之後才開始學的,看了一遍文檔之後就直接開幹,啥不會的就 CV 大法,還不會的就厚臉皮請教公司的前輩,就這樣過了差不多半年吧
- 2018年1月-6月。TL 看我已經逐漸掌握了前端技術棧的開發,也開始給我安排一些比較有挑戰性的活,負責一些日活比較高的項目日常維護和迭代。在這半年時間裏,更多時間還是在跟業務,沒有太多技術上的思考。當然,我的手還是非常快的,5天工作量的頁面我3天就能搞定,而且提測基本 0 bug。當然,這裏的手快不是敲鍵盤快,更多的是對於項目的理解和功能模塊的拆分,以及頁面組件、模塊的設計,保證複用度。這裏我的建議是:拿到一個業務需求,先理解透徹再動手編碼。理解包括對業務的理解和對需求的理解,將產品給到的 PRD 進行拆解分析,派出優先級和每項的排期,這樣對於整體項目都能有一個把控
- 2018年7月-12月。業務已經穩定,團隊也有了差不多差不多 8 個人,開始接手一些團隊基礎設施建設的事情,比如統一腳手架、統一 UI 組件庫以及統一技術棧的前期工作
- 2019年1月-6月。和 TL 一起推動統一了 React 作為前端統一技術棧,剛好拿到一個比較重要的業務,借這個項目沉澱了項目腳手架(包括中後台和 mobile),以及UI 組件庫(基於 antd 進行定製、封裝),在 3 月份的時候我也順利完成晉升(其實就是調了薪資)。從 18 年 7 月到 19 年 6 月這一年時間真的痛並快樂着,每天肝到最後一個下班,之前沒接觸過前端工程化體系,就沒日沒夜地學習。而且推動技術棧統一其實是一個很艱難的事情,這得拿出足夠的理由和證據讓團隊成員信服,並且得要有足夠的技術支撐(腳手架、組件庫、工程化能力、知識體系支撐),幸好 TL 也一直很支持這個事情,總算在肝了一年後順利建設了目前團隊的技術底座(當然還是比較 low 的,後面也一直在迭代
- 2019年7月-12月。基本做的就是腳手架、組件庫、工程化的完善的,以及 CI/CD 的一些事情
- 2020年1月-2020年6月。團隊的開發模式基本已經成型,只需要投入 2人日/周基本就可以。我們也開始沉澱團隊統一的埋點、監控方案,打造了統一的前端埋點管理系統、前端埋點工具、前端監控平台
- 2020年7月。雖然可能你覺得我三年來幹了很多事情,但是如果深入細節看,很多事情都是小打小鬧不成體系,業務量大了之後未必可以 cover。所以決定再次尋找自己新的定位,進入一個大廠,體系化地瞭解整個前端研發生命週期中大廠是如何思考和沉澱的
工作三年,學到很多。很多人可能會説:還是因為這家創業公司給力而且 TL 比較給力,所以可以待到三年。是的,這話沒毛病,我也很感謝我的 TL,感謝公司給了這樣一個平台讓我成長。
但是,我想説的是,除了外界客觀因素之外,自身的主觀因素也很重要。在上面的個人經歷中,我寫出來的可能都是讓你感覺很爽的事情,很多不爽的事情我沒寫出來而已。。
- 經常肝到半夜
- 被 TL 批評過,也經常懷疑過自我
- 暗地裏説過業務方(這人也太xx了,還天天摸魚)、罵過公司(公司也太xx了,遲早完蛋)
- 無數次想要離職的經歷,懂的人都懂,隨時都想砸了電腦走人
- ...
太多了,如果要寫,我可以寫出 100 條「我為什麼曾經無數次想要離職」。
人生就是這麼有意思,無數次想要離職都沒走,這次確是主動想要換個環境,並且需要放棄一些東西。
複習準備
掘金上關於面試的文章很多,這也是社區一個現狀,所以就挑了幾篇個人覺得比較好的着重看了一下:
- 2020年前端面試複習必讀文章:這個大佬的思維導圖整理的非常好,整個複習流程都是跟着這個導圖來的,而且也不用自己到處搜索文章了,相當方便
- 在阿里我是如何當面試官的 :這篇文章主要是瞭解一下阿里的面試是怎麼樣的,面試官關心什麼
- 面試分享:兩年工作經驗成功面試阿里P6總結 :實戰篇,真實的阿里大佬面試經驗
- 字節跳動今日頭條前端面經(4輪技術面+hr面):實戰篇,真實的字節大佬面試經驗
以上文章個人覺得就夠了,能花時間把這些知識啃下來,一般面試就沒什麼問題了。
簡歷準備
簡歷真的非常重要,校招的時候就有這樣的感覺,那時候有實習經歷和沒實習經歷簡直就是一個天一個地。這次也準備認真準備一下自己的簡歷。
對於簡歷,個人認為大廠面試官和 HR 最看重的是兩點:
- 項目經歷:做了什麼
- 工作經歷:穩定性
這裏就不展開説了,社區裏也很多優秀的文章。在這個過程中,我主要參考了以下幾篇文章,推薦一下:
- 《大廠面試》面試官看了直呼想要的簡歷
- 面試官到底想看什麼樣的簡歷?
- 教你如何寫初/高級前端簡歷【贈簡歷導圖】
面試題整理
這裏整理一下我這段時間面試遇到的面試題,按類型分一下,這裏只整理了我記錄的問題,來不及寫答案。。
JavaScript
1. 説説 JavaScript 的數據類型
算是面試官拿一個簡單的題給面試者熱熱身找找感覺吧。
- 基本數據類型:String、Boolean、Number、Symbol、null、undefined
- 引用數據類型:Object,如果要細分的話有 Object、Array、Date、RegExp 和 Function
2. 基本數據類型和引用數據類型有什麼區別?
很自然地就引出這個題,基本數據類型在被創建時,在棧上給其劃分一塊內存,將數值直接存儲在棧上; 引用數據類型在被創建時,首先在棧上創建一個引用,而對象的具體內容都存儲在堆內存上,然後由棧上面的引用指向堆中對象的地址。
3. 那基本數據類型和引用數據類型拷貝的時候有什麼區別?
由於存儲的位置不一樣,直接拷貝的時候就會有兩種情況:拷貝了值和拷貝了引用,也就是我們常説的深淺拷貝。
對於基本數據類型而言,沒有深淺拷貝的概念,都是在棧上新開闢了一塊內存給新的值。而對於引用數據類型而言,區別簡單來説就是會不會共享堆內存裏的值。具體不説了,文章很多,隨便看兩篇基本都沒啥問題。
- 深拷貝的終極探索(90%的人都不知道)
- JavaScript 專題之深淺拷貝
目前 JavaScript 的 API 中,哪些是淺拷貝,哪些是深拷貝?
可以看看這篇文章,雖然文章裏有一些小問題,不影響整體閲讀
- JavaScript 基礎心法——深淺拷貝
4. 如何實現一個深拷貝?
無非就是 JSON.stringify 和 遞歸 兩種方法,大概説説思路就 OK
5. 通過 JSON.stringify 的方式實現深拷貝,會有什麼問題?
如果值是 undefined、function 等,在轉換的時候會丟失,所以還是要比較謹慎使用 JSON.stringify 來做深拷貝
6. 通過遞歸的方式實現深拷貝,會有什麼問題?
循環引用和重複引用
數據類型和深淺拷貝的問題問到這裏基本差不多了。這裏説個小技巧:如果面試官問了第一題,面試官應該心裏已經有打算問你深淺拷貝的問題,如果你比較熟悉,也可以嘗試主動點往這方面引。
7. 數組去重的方式有哪些(手寫)
花裏胡哨的也就那幾種,主要考察對 JavaScript API 是否熟悉,我寫了兩種:Set 和 Hash,面試官也沒有多問。
Hash:
function unique(arr = []) {
if (arr.length === 0 || arr.length === 1) {
return arr;
}
const newArray = [];
const hash = {};
for (let i = 0; i < arr.length; i++) {
if (!hash[arr[i]]) {
hash[arr[i]] = 1;
newArray.push(arr[i]);
}
}
return newArray;
}
Set:
function unique(arr = []) {
if (arr.length === 0 || arr.length === 1) {
return arr;
}
return [...new Set(arr)];
}
8. 找出數組中最大的數(手寫)
我就只寫了一種
function getArrayMax(arr = []) {
if (!arr.length) return;
if (arr.length === 1) {
return arr[0];
}
return Math.max(...arr);
}
9. 説一下事件循環的理解
宏任務微任務那些,隨便搜都是,只推薦一篇經典文章:Tasks, microtasks, queues and schedules
10. 快排是如何實現的,講一下思路和複雜度
放兩張圖,感受一下,更多的動畫可以看 https://visualgo.net/zh/sorting
11. 如何實現一個觀察者模式(手寫)
12. 如何實現一個單例模式(手寫)
13. 如何解析一個 URL,獲取 query 和 hash 的參數(手寫)
14. TypeScript 和 JavaScript 最大的區別在哪
CSS
1. flex 如何實現九宮格
設 width,變 flex-wrap
2. 除了 flex 之外,還能如何實現九宮格
比較老的 float,比較新的 grid,然後展開説下 grid
3. flex: 1 是什麼意思
我就説了一下 flex: 1 的作用,然後説了一下 flex 其實有三個值,分別簡單説了一下各自的作用,就過了
4. 移動端適配怎麼做的,rem 原理是什麼,vw 有沒有了解
細説移動端 經典的REM佈局 與 新秀VW佈局
5. 移動端 1px 如何解決
- 移動端1px解決方案
- Retina屏的移動設備如何實現真正1px的線?
React/Vue
1. 看你的簡歷,Vue 和 React 都寫的比較多,可以説説 Vue 和 React 的區別嗎?
通過自己的理解,從編譯、生命週期、數據流、核心思想等方向都介紹了一下吧,這個問題還是需要認真準備一下,我説的時候感覺有點亂,回頭我看看寫一篇文章專門回答一下這個問題吧
2. 新項目的技術選型,你會從哪些方面來考慮選用 Vue 還是 React?
這個問題我聽到就感覺比較謹慎,因為本身就是在創業公司,面臨過很多次的技術選型。從 jQuery 到 Vue 和 React,我們也經歷了技術棧的更新換代。我們當時在考慮技術選型的時候,我們考慮的不是一個新項目,而是一個未來 2 - 3 年甚至更久的一個長遠技術選型,主要看了一下 React 和 Vue 的一個整體生態和完整度,當然這也包括社區的活躍度。因為我們並沒有太多人力做一些框架底層的工作以及一些生態周邊配套解決方案,更多的時候是拿一些現有的解決方案來解決我們的業務問題。
我在回答這個問題的時候,更多的時候是通過本身的業務出發回答的,沒有過多地回答 React 和 Vue 框架上的區別對技術選型帶來的影響。
3. 説説對虛擬 DOM 的理解
虛擬 DOM 本質上是一個真實 DOM 的抽象 JavaScript 對象。然後展開説了一下虛擬 DOM 的好處,操作 DOM 簡單、輕量、跨平台,我特別提了一下跨平台,Vue 2.x 之後引入的虛擬 DOM,也有一部分是為了解決未來跨平台的問題,後來也結合 WEEX 了。
4. 講講 React 的生命週期
這個沒啥好説的,根據自己的理解説一下那幾個生命週期了。也説了一下即將廢棄的生命週期以及為什麼廢棄,就過了。
5. React 函數式組件和類組件有什麼區別
6. React 的 diff 和 Vue 的有什麼區別
單向雙向的區別
7. 列表中的 key 有什麼作用
給 VirtualDOM diff 用
8. 説説 React Hooks 的理解,它有什麼優點
一篇看懂 React Hooks
9. React Hooks 不能出現在條件判斷語句中
可以確保每次渲染組件時都以相同的順序調用 Hook
10. 什麼是高階組件?
- 高階組件(HOC)應該是無副作用的純函數,且不應該修改原組件
- 高階組件(HOC)不關心你傳遞的數據(props)是什麼,並且被包裝組件不關心數據來源
- 高階組件(HOC)接收到的 props 應該透傳給被包裝組件
11. React 的高階組件和 Vue 的 mixins 是一個類型的東西嗎?Vue 中是否可以實現類似 React 的高階組件
高階組件本質就是高階函數,React 的組件是一個純粹的函數,所以高階函數對React來説非常簡單。
而 Vue 更像是高度封裝的函數,在更高的層面 Vue能夠讓你輕鬆的完成一些事情,但與高度的封裝相對的就是損失一定的靈活,你需要按照一定規則才能使系統更好的運行。
12. Vue 的雙向綁定是如何實現的
數據劫持和發佈訂閲
13. Vue 如何收集依賴
14. Vue 的父子組件掛載順序是怎麼樣的
父created -> 子created -> 子mounted -> 父mounted
15. Vue 的 computed 和 watch 是怎麼實現的
16. Vue 的 template 是如何編譯的
vue-loader 裏有然後專門處理 template 的 loader,最終本質上還是 createElement
17. Vue 3.0 和 2.x 有什麼區別
defineProperty、proxy,更開放的 API,ts 等等...
18. defineProperty 有什麼缺點,為什麼 Vue 3.0 之後改用 proxy
數組、對象的監聽
19. 我不是前端,你如何向我介紹 Vue,讓我能夠儘可能多的瞭解它
工程化
1. webpack 和 rollup 的區別
webpack 適用於大型複雜的前端站點構建,rollup 適用於基礎庫的打包
2. 説説 webpack 的 loader 和 plugin
loader 解析模塊,plugin 擴展功能
3. esbuild 有沒有了解
下一代構建工具,是使用 go編寫的,未來的趨勢會更多使用非 JavaScript 語言來編寫前端工具,優點是快。
4. CommonJS 和 ESM 有什麼區別
這個就不展開説了,找兩篇關於 JavaScript 模塊的文章看看就 OK
5. vite 和 snowpack 有了解嗎,unbundle 有什麼好處
個人理解會是未來構建工具的一種趨勢,在構建速度/熱更新速度上都比目前 webpack 的方案快非常多,大幅度提高前端開發效率。
6. webpack 的熱更新原理大概介紹一下
本地起服務,通過文件內容 hash 來判斷是否更新,客户端收到更新消息後會取拉取最新代碼進行更新
7. vue-loader 做了哪些事情
webpack 用於處理 .vue 文件的 loader,解析代碼,分別處理其中的 template/style/script...
8. tree sharking 是什麼
ESM,代碼體積優化,CommonJS 不支持
9. webpack4 相對於之前做了哪些優化
10. 項目中,你使用 webpack 做了哪些優化
- 使用
happypack加速構建 - 通過
analyze插件分析構建產物大小,優化體積 - chunk
- dll
- ...
11. 如何發佈一個 npm 包,如何發佈一個 beta 包,如何修改一個正式包為 beta 包
- npm publish
- npm publish --tag beta
- npm dist-tag add my-package@0.0.1-beta.0 beta
12. npm 包的版本號是如何規範的
參考 https://semver.org/lang/zh-CN/,這裏提了一下 break change 以及不規範的 npm 版本號會帶來什麼影響
13. DefinePlugin 的作用是什麼
定義全局變量,可以用於不同環境的代碼刪除
14. 你們團隊的項目腳手架是如何實現的
使用 Yeoman 開發的腳手架,介紹了一下 Yeoman 的能力,以及為什麼要用它而不是直接用現成的 cra 和 vue-cli
15. Babel 的原理是什麼
編譯器。分為三個階段:
- parse:詞法分析 語法分析
- transform:轉換ast
- generate:生成代碼
後端
1. Koa 和 Express 有什麼區別
- 異步:
callback和promise - 中間件:線性模型和洋葱模型
2. 説説 Koa 的中間件原理
3. 常用的 Node API 有哪些
4. SSR 是如何實現的
5. serverless 有了解嗎
6. 説説 node 的執行機制(單線程)
7. 為什麼説 node 是高性能的
8. node 為什麼支持高併發
- 執行速度快:運行在 Chrome V8 引擎上
- 異步:libuv 事件循環
- 適用 I/O 密集的網絡應用開發:解決網絡應用開發 I/O 的性能瓶頸
9. 説説 MVC 的思想
Model–view–controller
10. 説説 ORM 的優點
本質上是對 SQL 語句的一種抽象,方便(語句清晰),安全(一定程度防注入)
11. MySQL 和 MongoDB 有什麼區別
關係型數據庫和非關係數據庫
12. 依賴注入是什麼
網絡
1. 從輸入 URL 到頁面渲染,其中發生了什麼
這個問題真的很大,可以説很多東西,因為在問這個問題之前面試官在聊網絡,所以這個問題我也就回答了網絡方面相關的,至於瀏覽器渲染相關的我就隨便帶了一下就過了
2. HTTP 和 HTTPS 有什麼區別
從安全的角度説唄
3. 説説 HTTP 的狀態碼
隨便説了幾個常見的狀態碼,一般面試官問這個,其實是準備找幾個常見的狀態碼問你具體什麼意思,所以你就説自己比較瞭解的幾個就好了,如果完全沒了解過的,就別給自己挖坑了
4. 304 狀態碼是什麼意思
緩存
5. 瀏覽器的三級緩存策略瞭解嗎
- 先在內存中查找,如果有就加載
- 如果內存中不存在,則在硬盤中查找,如果有就加載
- 如果硬盤中也沒有,那麼就進行網絡請求
- 請求獲取的資源緩存到硬盤和內存
6. 説説瀏覽器的緩存,強緩存是什麼
7. websocket 是怎麼建立鏈接的
8. HTTPS 是如何保證網絡安全的
9. HTTP 如何實現長連接
keep-alive
算法(手寫)
1. 回形打印矩陣
2. 找出最長子字符串
3. 數組中的第 K 個最大元素
4. 用 JavaScript 實現一個鏈表
5. 從上到下打印二叉樹
其它
1. 介紹一個你覺得比較有亮點的項目
説了一個從 0 到 1 的項目,並且在這個項目中,我沉澱了一套目前公司統一使用的腳手架工具以及一個 UI 組件庫。由於是 0 到 1 的項目,項目週期中遇到了一些協作的問題,我也主動承擔了一些 PM 的角色,去推動項目正常運行,保證了項目正常上線,獲得業務上下游團隊的好評。
2. 在創業公司,一個前端項目的生命週期是怎麼樣的
在網上也看到了一些大廠的工作流程,相比來説,我們這邊的流程相對來説,大的骨幹都有,但是小的地方就顯得不夠規範。比如 Code Review、發佈管控、灰度回滾能力等,目前在我們的研發生命週期中,這些能力都只是 “能用” 的階段,目前我們也在加強規範建設。
3. 在團隊中,你是如何制定編碼規範的,如何推動規範落地的
根據目前業界常用的編碼規範,制定了編碼規範,以及一套 ESLint/StyleLint/CommitLintd 靜態檢查工具,當然還有 Prettier ,然後就是推廣大家用,用的過程中再迭代這套編碼規範。
4. 你還有什麼問題想問我的
不要頻繁跳槽
文章開始的時候有提到「不要頻繁跳槽」,這裏談談個人的看法。
對於面試官和 HR 來説,「頻繁跳槽」意味着兩點:
- 你的穩定性不足,得承擔給你發了 offer 之後你來到公司過了一段時間又跑路的風險,所以會是減分項
- 你沒有足夠的沉澱,技術和業務的沉澱是要時間的,對業務有深入的理解才能思考如何通過技術手段來解決業務上的問題
對於個人來説,「頻繁跳槽」意味着:
- 一直在準備面試,一直在刷題,沒有一個專項學習的時間段
- 技術棧一直在變,一直在適應,沒法更深入的理解
- 對業務不理解,對團隊不熟悉,惡性循環,又想跳槽
總結
這篇文章主要還是記錄一下自己這段時間以來的一些經歷,希望對大家能有幫助。之後也會輸出一些「全乾工程師」的技術文章在這裏,感興趣的朋友可以先關注。
當然,如果有空,我也會將我對上面面試題的回答都整理一下,發在社區上。
最近看大家都在流行公眾號,我也建了一個:full_stack_interview,感興趣的朋友可以關注一下,之後文章會優先發表在公眾號上,爭取做一個高質量的「全乾工程師」公眾號。
也可以加我微信:xiaolu950621 交流。