面經

原文鏈接:https://blog.csdn.net/qq_29438877/article/details/96942052

前言
筆者畢業於東北大學,大學畢業社招進入環球網,前端開發工程師一職。技術棧:React+node,Github 地址

成果
來到杭州的目標非常的明確,大廠。其實就是網易、阿里和滴滴。好在基本三家都拿到了offer。最終決定選擇阿里p6。

面試題
大廠流程比較長,比如阿里就面試了將近三週。所以期間也面試了很多別的公司,創業公司or上市公司。這裏我把我所被問到的面試題總結梳理一下。簡單深入的都有。筆者個人工作經驗不豐富,如若回答不好的地方歡迎指正。

HTML && CSS 部分
CSS常用佈局
CSS常用佈局爲盒模型div+css、其中需要注意IE的怪異盒模型,我們通常通過box-sizing解決。傳統盒模型佈局方式中我們可以細分爲文檔流佈局、浮動佈局、定位佈局。在ie10+中我們可以使用flex佈局,其中我們需要理解最爲核心的容器和軸的概念。二維佈局中,我們可以使用Grid佈局。對於三欄佈局,除了浮動實現方式,還有雙飛翼佈局和聖盃佈局。其實雙飛翼佈局就是對聖盃佈局的bug修復,一種改造升級。

瞭解BFC麼?
BFC即爲塊級格式化上下文。在普通流的Box屬於一種formatting box,類型可以爲block或者爲inline。但是不能同時爲這兩者。並且Block boxes在block formatting context裏格式化,inline boxes在inline formatting context中格式化,任何被渲染的元素都屬於一個box,不是block就是inline。其一般表現規則分爲以下幾種情況:1、在創建了BFC的元素中,其子元素按照文檔流一個接着一個放置。垂直方向上他們的起點是一個包含塊的頂部,兩者相鄰元素的垂直距離取決margin特性。2、在BFC中,每一個元素的左外邊與包含塊的左邊相接觸。及時存在浮動也是如此。除非這個元素也創建了一個新的BFC。3、BFC就是頁面的一個獨立的行政區域。所有瀏覽器都會將BFC放到浮動元素所在行的剩餘空間內。當HTML滿足一下任意一個條件即可產生BFC:float不爲none、overflow不爲hidden、display爲table-cell,table-caption,inline-block中的任何一個。Position值不爲relative或static。通常我們使用BFC爲了不和浮動元素重疊。清除內部浮動元素。解決上下元素相鄰時候重疊。

居中方面問題
分別從水平居中垂直居中兩方面回答。水平、垂直居中分爲單個元素、多個元素、已知寬高和未知寬高回答

session、cookie、sessionStorage、localStorage區別
從client和Server中區分回答session是什麼以及一般session如何使用注意事項以及安全策略,cookie、sessionStorage和localStorage等分別從概念和異同處回答。最後補充項目中的使用情況

px/em/rem的區別
px顧名思義就是我們通常說的像素大小。em和rem都是相對大小,不過em是繼承父級元素的字體大小,rem是相對於根元素的大小,這個單位可謂是集相對大小和絕對大小爲一身。通過它可以做到只修改根元素即可修改所有字體的大小,又可以避免字體大小逐層複合的連鎖反應。當rem相對於瀏覽器進行縮放,1rem默認爲16px。

animation和transition使用過麼
寫法:animation:name duration timing-function delay iteration-function direction .transition爲過渡動畫,這種效果可以在事件中觸發,並且圓滑的以動畫效果改變css的屬性值。不同於transform,transform爲2D轉換(問題非常開放,儘可能多回答你所知道的)

css編寫注意事項
這個考驗個人平時編碼的總結和約束。問題較爲開放,可以結合個人開發體驗和團隊約束來回答。比如0後面不帶單位、儘量使用簡寫、使用子選擇器、合理使用id等。

JavaScript部分
JavaScript閉包瞭解麼
閉包即爲函數,但是我們通常所說的閉包是指有權訪問並操作別的函數作用域中變量的函數。一般表現形式爲函數中返回函數。通常我們開發中就會有很多的閉包比如定時器、事件監聽、IIFE等。此題是一個借題發揮漲分的題目,我們可以談談閉包的高級用法,比如單例模式中的使用、js的節流和防抖甚至可以談一談js的運行機制,gc機制。

前端跨域都有哪些解決方案
js的前端跨域很多,通常我們給出方案並且應該簡述優缺點,比如方式有,jsonp、document.domain+iframe、window.name+ifram、location.hash+iframe、postMessage跨域、CORS跨域、websocket跨域、node代理跨域以及NGINX代理等方式。其中對於我們常用的可以張開說明,比如CORS跨域中簡單請求和非簡單請求的header字段,access-control-allow-origin、access-control-allow-headers、access-control-allow-method等常規head字段說明。

JavaScript中的繼承
1、Es6中我們直接可以使用extends關鍵字去繼承,通過重寫super完成繼承,但是在es5中,纔是應該去主要細說的。2.原型繼承的核心爲父類的實例作爲子類的原型。優點:非常純粹的繼承關係、簡單易用、父類新增的原型方法原型屬性子類都可以訪問到。缺點:要爲子類新增屬性和方法,必須要放到new Animal()之後,不能放到構造器中,來自原型對象的引用類型被所有實力共享,創建子類,無法向構造函數傳參。3.構造函數繼承核心:使用父類構造函數來增強子類的實例優點:解決了共享引用類型的問題,可以在構造函數裏面傳參,可以實現多繼承。缺點:實例不是父類實例,只能繼承父類的屬性和方法,不能繼承父類原型的方法和屬性、無法實現函數的複用。4、組合繼承的核心:通過調用父類的構造,繼承父類的屬性並保留參數的有點,通過父類的實例作爲子類原型,實現函數複用。優點:可以繼承屬性和方法以及原型上的屬性和方法、即是子類實例也是父類實例、不存在屬性共享的問題、函數可複用。缺點:調用了兩次構造函數,生成了兩份實例。5、寄生組合繼承核心:砍掉父類的實例屬性,這樣,在調用兩次父類的構造時候,就不會初始化兩次實例方法和屬性,避免組合繼承的缺點
es6 extends繼承,ES5中的繼承,實質上是先創建子類上的this,然後再將父類方法添加到this上,es6則是先創建父類的實例方法(必須調用super),然後在用子類構造函數修改this。沒有調用super,是沒有this的。

JavaScript中的節流和防抖
防抖的原理爲觸發事件的n時間後才執行,如果n時間內事件再次被觸發,則以新觸發的時間爲標準,然後n事件後再執行

節流的原理爲在持續觸發事件時候,每隔一段時間執行一次。我們可以使用time line或者定時器來實現,或者二者結合實現。


JavaScript中的事件你瞭解哪些
這種題目一般爲開放性的題目,首先我們可以從事件的階段來回答,事件冒泡、事件捕獲、以及目標階段。同時我們可以說明下事件委託的使用方式以及瀏覽器兼容性的問題。

setTimeout設置爲0發生了什麼
這主要考察js的執行機制,可以從event loop來回答,包括js的單線程以及task queue microtask queue等。

原生ajax請求瞭解麼


js判斷數據類型的幾種方法
1、最常見的typeof,返回的String格式。能夠判斷function,但是判斷Object比較煩。2、判斷已知數據類型可以用instanceof,注意instanceof後面一定是對象類型,並且大小寫不能錯。3.constructor方式。但是在實現繼承的時候回出現錯誤,需要手動修改。4.通用但是很繁瑣的方法爲prototype:Object.prototype.toString.call(a)

this指向問題
1、常規爲題,從默認綁定、隱含綁定、明確綁定以及new綁定來回答。2、擴展es6中的箭頭函數,以及call、apply和bind的區別。

你如何看待JavaScript這門語言
開放新問題,可以從參考《JavaScript語言精粹》,談談自己開發中遇到的各種問題,最重要的不是吐槽而是對雞肋的解決辦法,比如繼承的實現、塊級作用域、變量提升等。

es6用過麼?說說promise的實現
關於es6的知識點這裏不再贅述。Promise的實現主要是pub-sub模式。狀態和行爲相分離的難點。

React部分
react組件的生命週期相關
react組件生命週期最好的提現是使用es5 的編碼方式,其中生命線大概分爲兩條路線,分別爲getDefaultProps、getInitialState、componentWillMount、render、componentDidMount、(Running),然後分爲兩路,componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate以及componentWillUumount。我們一般在getInitialState中初始化組件的狀態數據,在componentDidMount或者componentWillMount中進行獲取API請求操作等,在shouldComponentUpdate中進行組件的優化。其中可以展開如何優化以及官方推薦的PureRenderMixin等實現方式。以及別的方面擴展結合自己的開發經驗。

setState是同步的還是異步的
通常我們的寫法都是異步的,但是真正想要我們回答的是當給setState傳入函數的時候,其實表現的爲同步的。

子組件的componentDidMount和父組件的componentDidMount哪一個先執行?
必然是子組件的componentDidMount限制性,可以從react組件的生命週期進行分析擴展。

react的DIFF算法和virtual dom瞭解多少?

React的render函數返回的是一個DOM描述,結果僅僅是輕量級的js對象,reactjs在調用setState的時候會更新DOM,而且是先更新virtual dom,然後和實際dom比較,最後更新dom。React厲害的地方不是說他比真實的dom速度快,而是你不敢數據怎麼變化,我都以最小的代價來更新視圖。方法就是我在內存當中使用新的數據來構建一個virtual dom,然後和舊DOM進行比較,找出差異,然後更新到DOM節點上。當我們修改dom上的一個節點對應的state,react會立即將他標記爲“髒狀態”,在事件循環的最後才重新渲染所有的髒節點。在實際的代碼中,會對新舊兩棵樹進行一次深度優先遍歷,這樣每一個節點都會有一個唯一的標記,沒遍歷到一個節點,就把該節點和新的樹進行比較,如果有差異就記錄到一個對象中,最後把差異應用到真正的DOM樹上。算法實現步驟爲:用js對象模擬DOM樹,比較兩顆虛擬DOM的差異,把差異應用到真正的DOM樹上,DOM DIFF採用的是增量更新的方式,類似於打補丁。React需要爲節點添加key來保證算法的效率。Key屬性可以幫助react定位到正確的節點進行比較。從而大幅度減少DOM操作,提高性能。

MVC和MVVM瞭解麼?可以大致說一下雙向綁定的實現方式麼?

Modal層代表數據模型,可以再modal層定義修改和操作數據的邏輯,view代表UI層,負責將數據轉換成UI展現出來,viewModal是同步view和modal的對象。用戶操作view層,view數據變化會同步到modal上,modal數據變化會立即反應到view中,viewModal通過實現雙向綁定來將view和modal連接到一起。而雙向綁定,我們可以從髒檢查到標記更新來回答。

前端路由的實現方式
從react當中我們可以說說react router的使用和原理,以及h5中的historyAPI,pushState和replaceState來回答。

a組件是b組件的父組件,b組件是c組件的父組件,如何讓渲染後的b和c在同級
通過react16中不返回容器組件可以實現,也可以通過“曲線救國”的方式來實現。

react SSR瞭解麼
react ssr有很多種實現方式,但是原理不變,目的就是爲了減少首屏白屏時間以及有好的SEO。對於實現方式我們可以從next.js以及webpack-isomorphic-tools來說實現。

瀏覽器相關
http三次握手後拿到HTML是如何進行加載的?

考覈的主要是瀏覽器加載頁面的機制。大概可以從瀏覽器拿到HTML,自上而下開始解析,大致分爲解析DOM,解析CSSOM,構建渲染樹,佈局階段以及繪製階段來說明。其實儘可能的詳細說明,比如構建DOM的時候分別通過Bytes、characters、tokens、Nodes最終到DOM等。回答也可以擴展repaint和reflow等瀏覽器優化。

簡述瀏覽器優化


200 From cache和200 OK有什麼區別?

顧名思義是form cache是強緩存,不會和服務器通信,而200OK即爲服務器處理結果正確。以此可以從瀏覽器緩存、輸入url回車、刷新頁面以及強制刷新等方面展開緩存方面的講解。

http2.0新特性瞭解嗎

1、2採用二進制而非文本格式,二進制協議解析起來更高效。
2、採用多路複用,即爲同一個tcp連接上可以建立多個http連接,那樣的話,我們雪碧圖就沒有必要了。
3、使用報文頭壓縮,降低了開銷。
4.可以讓服務器主動向瀏覽器推送消息,支持服務端推送,也就是服務端可以對客戶端有多個響應。

post和get有什麼區別?

1 、GET把參數包含在URL中,POST通過request body傳遞參數。
2、GET在瀏覽器回退時是無害的,而POST會再次提交請求。GET產生的URL地址可以被Bookmark,而POST不可以。GET請求會被瀏覽器主動cache,而POST不會,除非手動設置。GET請求只能進行url編碼,而POST支持多種編碼方式。GET請求參數會被完整保留在瀏覽器歷史記錄裏,而POST中的參數不會被保留。GET請求在URL中傳送的參數是有長度限制的,而POST麼有。對參數的數據類型,GET只接受ASCII字符,而POST沒有限制。GET比POST更不安全,因爲參數直接暴露在URL上,所以不能用來傳遞敏感信息。GET參數通過URL傳遞,POST放在Request body中。
3、GET和POST是什麼?HTTP協議中的兩種發送請求的方法。
4、HTTP是什麼?HTTP是基於TCP/IP的關於數據如何在萬維網中如何通信的協議。5、HTTP的底層是TCP/IP。所以GET和POST的底層也是TCP/IP,也就是說,GET/POST都是TCP鏈接。GET和POST能做的事情是一樣一樣的。你要給GET加上request body,給POST帶上url參數,技術上是完全行的通的。
6、在我大萬維網世界中,還有另一個重要的角色:運輸公司。不同的瀏覽器(發起http請求)和服務器(接受http請求)就是不同的運輸公司。雖然理論上,你可以在車頂上無限的堆貨物(url中無限加參數)。但是運輸公司可不傻,裝貨和卸貨也是有很大成本的,他們會限制單次運輸量來控制風險,數據量太大對瀏覽器和服務器都是很大負擔。業界不成文的規定是,(大多數)瀏覽器通常都會限制url長度在2K個字節,而(大多數)服務器最多處理64K大小的url。超過的部分,恕不處理。如果你用GET服務,在request body偷偷藏了數據,不同服務器的處理方式也是不同的,有些服務器會幫你卸貨,讀出數據,有些服務器直接忽略,所以,雖然GET可以帶request body,也不能保證一定能被接收到哦。
7、GET產生一個TCP數據包;POST產生兩個TCP數據包。
8、對於GET方式的請求,瀏覽器會把http header和data一併發送出去,服務器響應200(返回數據);而對於POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。也就是說,GET只需要汽車跑一趟就把貨送到了,而POST得跑兩趟,第一趟,先去和服務器打個招呼“嗨,我等下要送一批貨來,你們打開門迎接我”,然後再回頭把貨送過去。因爲POST需要兩步,時間上消耗的要多一點,看起來GET比POST更有效。因此Yahoo團隊有推薦用GET替換POST來優化網站性能。但這是一個坑!跳入需謹慎。爲什麼?1. GET與POST都有自己的語義,不能隨便混用。2. 據研究,在網絡環境好的情況下,發一次包的時間和發兩次包的時間差別基本可以無視。而在網絡環境差的情況下,兩次包的TCP在驗證數據包完整性上,有非常大的優點。3. 並不是所有瀏覽器都會在POST中發送兩次包,Firefox就只發送一次。

構建工具
瞭解過webpack編譯過程嗎?

Webpack 的運行流程是一個串行的過程,從啓動到結束會依次執行以下流程,1、初始化參數:從配置文件和 Shell 語句中讀取與合併參數,得出最終的參數;2、開始編譯:用上一步得到的參數初始化 Compiler 對象,加載所有配置的插件,執行對象的 run 方法開始執行編譯;3、確定入口:根據配置中的 entry 找出所有的入口文件;4、編譯模塊:從入口文件出發,調用所有配置的 Loader 對模塊進行翻譯,再找出該模塊依賴的模塊,再遞歸本步驟直到所有入口依賴的文件都經過了本步驟的處理;5、完成模塊編譯:在經過第4步使用 Loader 翻譯完所有模塊後,得到了每個模塊被翻譯後的最終內容以及它們之間的依賴關係;6、輸出資源:根據入口和模塊之間的依賴關係,組裝成一個個包含多個模塊的 Chunk,再把每個 Chunk 轉換成一個單獨的文件加入到輸出列表,這步是可以修改輸出內容的最後機會;7、輸出完成:在確定好輸出內容後,根據配置確定輸出的路徑和文件名,把文件內容寫入到文件系統。在以上過程中,Webpack 會在特定的時間點廣播出特定的事件,插件在監聽到感興趣的事件後會執行特定的邏輯,並且插件可以調用 Webpack 提供的 API 改變 Webpack 的運行結果。

編寫過webpack插件嗎

1、Webpack 通過 Plugin 機制讓其更加靈活,以適應各種應用場景。在 Webpack 運行的生命週期中會廣播出許多事件,Plugin 可以監聽這些事件,在合適的時機通過 Webpack 提供的 API 改變輸出結果。2、Webpack 啓動後,在讀取配置的過程中會先執行 new BasicPlugin(options) 初始化一個 BasicPlugin 獲得其實例。在初始化 compiler 對象後,再調用 basicPlugin.apply(compiler) 給插件實例傳入 compiler 對象。插件實例在獲取到 compiler 對象後,就可以通過 compiler.plugin(事件名稱, 回調函數) 監聽到 Webpack 廣播出來的事件。並且可以通過 compiler 對象去操作 Webpack。3、在開發 Plugin 時最常用的兩個對象就是 Compiler 和 Compilation,它們是 Plugin 和 Webpack 之間的橋樑。Compiler 和 Compilation 的含義如下:Compiler 對象包含了 Webpack 環境所有的的配置信息,包含 options,loaders,plugins 這些信息,這個對象在 Webpack 啓動時候被實例化,它是全局唯一的,可以簡單地把它理解爲 Webpack 實例;Compilation 對象包含了當前的模塊資源、編譯生成資源、變化的文件等。當 Webpack 以開發模式運行時,每當檢測到一個文件變化,一次新的 Compilation 將被創建。Compilation 對象也提供了很多事件回調供插件做擴展。通過 Compilation 也能讀取到 Compiler 對象。4、Compiler 和 Compilation 的區別在於:Compiler 代表了整個 Webpack 從啓動到關閉的生命週期,而 Compilation 只是代表了一次新的編譯。5、開發插件時需要注意:只要能拿到 Compiler 或 Compilation 對象,就能廣播出新的事件,所以在新開發的插件中也能廣播出事件,給其它插件監聽使用、傳給每個插件的 Compiler 和 Compilation 對象都是同一個引用。也就是說在一個插件中修改了 Compiler 或 Compilation 對象上的屬性,會影響到後面的插件、有些事件是異步的,這些異步的事件會附帶兩個參數,第二個參數爲回調函數,在插件處理完任務時需要調用回調函數通知 Webpack,纔會進入下一處理流程。

開發過webpack loader麼

1、一個 Loader 的職責是單一的,只需要完成一種轉換。如果一個源文件需要經歷多步轉換才能正常使用,就通過多個 Loader 去轉換。在調用多個 Loader 去轉換一個文件時,每個 Loader 會鏈式的順序執行, 第一個 Loader 將會拿到需處理的原內容,上一個 Loader 處理後的結果會傳給下一個接着處理,最後的 Loader 將處理後的最終結果返回給 Webpack。2、所以,在你開發一個 Loader 時,請保持其職責的單一性,你只需關心輸入和輸出。


感悟
以上問題包括但不全面對於這次杭州的求職。總的來說,你的簡歷就是你給面試官的考綱,所以簡歷一定要真實,及時面試過程中遇到不會的題目,也要沉着冷靜思考,不會也要主動承認,然後最好能夠提出自己的思考和猜測。千萬別不懂裝懂!千萬別不懂裝懂!千萬別不懂裝懂!

前端,個人還是覺得基礎很重要,從基礎到框架,從框架就到原理,從原理到源碼,一步一腳印。一定要自信,直面面試官,表現出自己最好的狀態。同事別太咄咄逼人,一定要尊敬面試官,禮貌。

最後,還是希望每一個求職者,都能夠進入自己如願以償的公司拿到心儀的offer~
--------------------- 
版權聲明:本文爲CSDN博主「isNealyang」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_29438877/article/details/96942052

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章