前言
最近參加了幾場面試,積累了一些高頻面試題,我把面試題分為兩類,一種是基礎試題: 主要考察前端技基礎是否紮實,是否能夠將前端知識體系串聯。一種是開放式問題: 考察業務積累,是否有自己的思考,思考問題的方式,這類問題沒有標準答案。
基礎題
題目的答案提供了一個思考的方向,答案不一定正確全面,有錯誤的地方歡迎大家請在評論中指出,共同進步。
怎麼去設計一個元件封裝
- 元件封裝的目的是為了重用,提高開發效率和程式碼質量
- 低耦合,單一職責,可複用性,可維護性
- 前端元件化設計思路
js 非同步載入的方式
- 渲染引擎遇到 script 標籤會停下來,等到執行完指令碼,繼續向下渲染
- defer 是“渲染完再執行”,async 是“下載完就執行”,defer 如果有多個指令碼,會按照在頁面中出現的順序載入,多個async 指令碼不能保證載入順序
- 載入 es6模組的時候設定 type=module,非同步載入不會造成阻塞瀏覽器,頁面渲染完再執行,可以同時加上async屬性,非同步執行指令碼(利用頂層的this等於undefined這個語法點,可以偵測當前程式碼是否在 ES6 模組之中)
css 動畫和 js 動畫的差異
- 程式碼複雜度,js 動畫程式碼相對複雜一些
- 動畫執行時,對動畫的控制程度上,js 能夠讓動畫,暫停,取消,終止,css動畫不能新增事件
- 動畫效能看,js 動畫多了一個js 解析的過程,效能不如 css 動畫好
XSS 與 CSRF 兩種跨站攻擊
- xss 跨站指令碼攻擊,主要是前端層面的,使用者在輸入層面插入攻擊指令碼,改變頁面的顯示,或則竊取網站 cookie,預防方法:不相信使用者的所有操作,對使用者輸入進行一個轉義,不允許 js 對 cookie 的讀寫
- csrf 跨站請求偽造,以你的名義,傳送惡意請求,通過 cookie 加引數等形式過濾
- 我們沒法徹底杜絕攻擊,只能提高攻擊門檻
事件委託,目的,功能,寫法
- 把一個或者一組元素的事件委託到它的父層或者更外層元素上
- 優點,減少記憶體消耗,動態繫結事件
- target 是觸發事件的最具體的元素,currenttarget是繫結事件的元素(在函式中一般等於this)
- JavaScript 事件委託詳解
執行緒,程式
- 執行緒是最小的執行單元,程式是最小的資源管理單元
- 一個執行緒只能屬於一個程式,而一個程式可以有多個執行緒,但至少有一個執行緒
負載均衡
- 當系統面臨大量使用者訪問,負載過高的時候,通常會使用增加伺服器數量來進行橫向擴充套件,使用叢集和負載均衡提高整個系統的處理能力
- 伺服器叢集負載均衡原理?
什麼是CDN快取
- CDN 是一種部署策略,根據不同的地區部署類似nginx 這種服務服務,會快取靜態資源。前端在專案優化的時候,習慣在講臺資源上加上一個 hash 值,每次更新的時候去改變這個 hash,hash 值變化的時候,服務會去重新取資源
- (CDN)是一個經策略性部署的整體系統,包括分散式儲存、負載均衡、網路請求的重定向和內容管理4個要件
- CDN_百度百科
閉包的寫法,閉包的作用,閉包的缺點
- 使用閉包的目的——隱藏變數,間接訪問一個變數,在定義函式的詞法作用域外,呼叫函式
- 閉包的記憶體洩露,是IE的一個 bug,閉包使用完成之後,收回不了閉包的引用,導致記憶體洩露
- 「每日一題」JS 中的閉包是什麼?
- 閉包造成記憶體洩露的實驗
跨域問題,誰限制的跨域,怎麼解決
- 瀏覽器的同源策略導致了跨域
- 用於隔離潛在惡意檔案的重要安全機制
- [jsonp ,允許 script 載入第三方資源]https://segmentfault.com/a/11…
- nginx 反向代理(nginx 服務內部配置 Access-Control-Allow-Origin *)
- cors 前後端協作設定請求頭部,Access-Control-Allow-Origin 等頭部資訊
- iframe 巢狀通訊,postmessage
javascript 中常見的記憶體洩露陷阱
- 記憶體洩露會導致一系列問題,比如:執行緩慢,崩潰,高延遲
- 記憶體洩露是指你用不到(訪問不到)的變數,依然佔居著記憶體空間,不能被再次利用起來
- 意外的全域性變數,這些都是不會被回收的變數(除非設定 null 或者被重新賦值),特別是那些用來臨時儲存大量資訊的變數
- 周期函式一直在執行,處理函式並不會被回收,jq 在移除節點前都會,將事件監聽移除
- js 程式碼中有對 DOM 節點的引用,dom 節點被移除的時候,引用還維持
- JavaScript 中 4 種常見的記憶體洩露陷阱
babel把ES6轉成ES5或者ES3之類的原理是什麼
- 它就是個編譯器,輸入語言是ES6+,編譯目標語言是ES5
- babel 官方工作原理
- 解析:將程式碼字串解析成抽象語法樹
- 變換:對抽象語法樹進行變換操作
- 再建:根據變換後的抽象語法樹再生成程式碼字串
Promise 模擬終止
- 當新物件保持“pending”狀態時,原Promise鏈將會中止執行。
- return new Promise(()=>{}); // 返回“pending”狀態的Promise物件
- 從如何停掉 Promise 鏈說起(promise記憶體洩漏問題)
promise 放在try catch裡面有什麼結果
- Promise 物件的錯誤具有冒泡性質,會一直向後傳遞,直到被捕獲為止,也即是說,錯誤總會被下一個catch語句捕獲
- 當Promise鏈中丟擲一個錯誤時,錯誤資訊沿著鏈路向後傳遞,直至被捕獲
網站效能優化
- http 請求方面,減少請求數量,請求體積,對應的做法是,對專案資源進行壓縮,控制專案資源的 dns 解析在2到4個域名,提取公告的樣式,公共的元件,雪碧圖,快取資源,
- 壓縮資源,提取公共資源壓縮,提取 css ,js 公共方法
- 不要縮放圖片,使用雪碧圖,使用字型圖表(阿里向量相簿)
- 使用 CDN,拋開無用的 cookie
- 減少重繪重排,CSS屬性讀寫分離,最好不要用js 修改樣式,dom 離線更新,渲染前指定圖片的大小
- js 程式碼層面的優化,減少對字串的計算,合理使用閉包,首屏的js 資源載入放在最底部
js 自定義事件實現
- 原生提供了3個方法實現自定義事件
- createEvent,設定事件型別,是 html 事件還是 滑鼠事件
- initEvent 初始化事件,事件名稱,是否允許冒泡,是否阻止自定義事件
- dispatchEvent 觸發事件
angular 雙向資料繫結與vue資料的雙向資料繫結
- 二者都是 MVVM 模式開發的典型代表
- angular 是通過髒檢測實現,angular 會將 UI 事件,請求事件,settimeout 這類延遲,的物件放入到事件監測的髒佇列,當資料變化的時候,觸發 $diget 方法進行資料的更新,檢視的渲染
- vue 通過資料屬性的資料劫持和釋出訂閱的模式實現,大致可以理解成由3個模組組成,observer 完成對資料的劫持,compile 完成對模板片段的渲染,watcher 作為橋樑連線二者,訂閱資料變化及更新檢視
get與post 通訊的區別
- Get 請求能快取,Post 不能
- Post 相對 Get 安全一點點,因為Get 請求都包含在 URL 裡,且會被瀏覽器儲存歷史紀錄,Post 不會,但是在抓包的情況下都是一樣的。
- Post 可以通過 request body來傳輸比 Get 更多的資料,Get 沒有這個技術
- URL有長度限制,會影響 Get 請求,但是這個長度限制是瀏覽器規定的,不是 RFC 規定的
- Post 支援更多的編碼型別且不對資料型別限制
有沒有去研究webpack的一些原理和機制,怎麼實現的
- 解析webpack配置引數,合併從shell傳入和webpack.config.js檔案裡配置的引數,生產最後的配置結果。
- 註冊所有配置的外掛,好讓外掛監聽webpack構建生命週期的事件節點,以做出對應的反應。
- 從配置的entry入口檔案開始解析檔案構建AST語法樹,找出每個檔案所依賴的檔案,遞迴下去。
- 在解析檔案遞迴的過程中根據檔案型別和loader配置找出合適的loader用來對檔案進行轉換。
- 遞迴完後得到每個檔案的最終結果,根據entry配置生成程式碼塊chunk。
- 輸出所有chunk到檔案系統。
ES6模組與CommonJS模組的差異
- CommonJs 模組輸出的是一個值的拷貝,ES6模組輸出的是一個值的引用
- CommonJS 模組是執行時載入,ES6模組是編譯時輸出介面
- ES6輸入的模組變數,只是一個符號連結,所以這個變數是隻讀的,對它進行重新賦值就會報錯
模組載入AMD,CMD,CommonJS Modules/2.0 規範
- 這些規範的目的都是為了 JavaScript 的模組化開發,特別是在瀏覽器端的
- 對於依賴的模組,AMD 是提前執行,CMD 是延遲執行
- CMD 推崇依賴就近,AMD 推崇依賴前置
Node 事件迴圈,js 事件迴圈差異
- Node.js 的事件迴圈分為6個階段
- 瀏覽器和Node 環境下,microtask 任務佇列的執行時機不同
- Node.js中,microtask 在事件迴圈的各個階段之間執行
- 瀏覽器端,microtask 在事件迴圈的 macrotask 執行完之後執行
- 遞迴的呼叫process.nextTick()會導致I/O starving,官方推薦使用setImmediate()
淺拷貝和深拷貝的問題
- 深拷貝和淺拷貝是隻針對Object和Array這樣的複雜型別的
- 也就是說a和b指向了同一塊記憶體,所以修改其中任意的值,另一個值都會隨之變化,這就是淺拷貝
- 淺拷貝, ”Object.assign() 方法用於將所有可列舉的屬性的值從一個或多個源物件複製到目標物件。它將返回目標物件
- 深拷貝,JSON.parse()和JSON.stringify()給了我們一個基本的解決辦法。但是函式不能被正確處理
開放性問題
開放性問題主要是考察候選人業務積累,是否有自己的思考,思考問題的方式,沒有標準答案。不過有些問題挺刁的,哈哈哈哈,比如:” 你見過的最好的程式碼是什麼? “總之提前準備下沒錯。
- 先自我介紹一下,說一下專案的技術棧,以及專案中遇到的一些問題
- 從整體中,看你對專案的認識,框架的認識和自己思考
- 專案中有沒有遇到什麼難點,怎麼解決
- 如果你在創業公司你怎麼從0開始做(選擇什麼框架,選擇什麼構建工具)
- 說一下你專案中用到的技術棧,以及覺得得意和出色的點,以及讓你頭疼的點,怎麼解決的
- 一個業務場景,面對產品不斷迭代,以及需求的變動該怎麼應對,具體技術方案實現
- 你的學習來源是什麼
- 你覺得哪個框架比較好,好在哪裡
- 你覺得最難得技術難點是什麼
- 你見過的最好的程式碼是什麼
?往期的讀書筆記
為了系統的串聯前端知識,我平時喜歡用思維導圖來記錄讀書筆記,我在 github 建了倉庫放這些思維導圖的原件,和讀書筆記。如果你也喜歡用思維導圖的方式來記錄讀書筆記,也歡迎和我一同維護這個倉庫,歡迎留言或則微信(646321933)與我交流