国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

校招社招必備核心前端面試問題與詳細解答

jonh_felix / 512人閱讀

摘要:本文總結(jié)了前端老司機經(jīng)常問題的一些問題并結(jié)合個人總結(jié)給出了比較詳盡的答案。網(wǎng)易阿里騰訊校招社招必備知識點。此外還有網(wǎng)絡(luò)線程,定時器任務(wù)線程,文件系統(tǒng)處理線程等等。線程核心是引擎。主線程和工作線程之間的通知機制叫做事件循環(huán)。

本文總結(jié)了前端老司機經(jīng)常問題的一些問題并結(jié)合個人總結(jié)給出了比較詳盡的答案。網(wǎng)易阿里騰訊校招社招必備知識點。
關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-你不知道的那些細節(jié)
課程知識在不斷更新,本片內(nèi)容也逐步更新
官方博客:FED123前端學(xué)堂

1.關(guān)于性能優(yōu)化說說js文件擺放順序、減少請求、雪碧圖等等原理, 說下window.performance.timing api是干什么的?

瀏覽器是按照文檔流解析html,為了更快構(gòu)建DOM樹和渲染樹將頁面呈現(xiàn)到屏幕上,建議是降js放在文檔dom樹結(jié)尾,body標(biāo)簽閉合前。
瀏覽器并發(fā)HTTP請求有限制(6個左右),加載頁面html后開始解析,解析到外鏈資源比如js css和圖片,就會發(fā)http請求獲取對應(yīng)資源。減少請求就是減少這些資源請求, 可以 css資源合并,js資源合并,圖片資源合并同時做lazyload,區(qū)分首屏非首屏接口,按需請求數(shù)據(jù)。
雪碧圖是一種圖片資源的合并方法,將一些小圖片合成一張圖,通過background-position來定位到對應(yīng)部分。
window.performance.timing 參考下前端頁面性能指標(biāo)數(shù)據(jù)計算方法, performance接口屬于w3c標(biāo)準(zhǔn)hight resolution time中的一部分,通過navigation timeline api 、 performance timeline api,user timing api,resource timeline api 這四個接口做了增強實現(xiàn)。其中navigation timeline api中PerformanceTiming?接口數(shù)據(jù)放在?performance.timing這個對象上。主要記錄了瀏覽器從跳轉(zhuǎn)開始的各個時間點的時間,比如navigationStart是頁面開始跳轉(zhuǎn)時間,fetchStart是頁面開始時間,domainLookupStart是DNS開始時間,domainLookupEnd是DNS結(jié)束時間, 查找到DNS后建立http鏈接,connectStart和connectEnd分別是鏈接開始和結(jié)束時間,然后是requestStart開始發(fā)起請求時間,responseStart開始響應(yīng)時間,responseEnd響應(yīng)結(jié)束時間。然后是茍安DOM樹時間,分別是domLoading, domInteractive, domContentLoad和domComplete時間,分別對應(yīng)document.readyState狀態(tài)loading、interactive和complete。最后是頁面onload,分別是loadEventStart和loadEventEnd時間節(jié)點。

可以通過這個接口統(tǒng)計前端的頁面性能數(shù)據(jù)。

domainLookupStart -?fetchStart = appCache時間,這段時間瀏覽器首先檢查緩存
domainLookupEnd -domainLookupStart = DNS時間
connectEnd - connectStart = TCP時間
responseStart - requestStart = FTTB首字節(jié)時間,或者說是服務(wù)器響應(yīng)等待時間
domContentLoad -?navigationStart = 頁面pageLoad時間
?loadEventEnd -?navigationStart = 頁面onLoad時間

關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端

2.請你描述下一個網(wǎng)頁是如何渲染出來的,dom樹和css樹是如何合并的,瀏覽器的運行機制是什么,什么是否會造成渲染阻塞?

參考下:瀏覽器工作原理???瀏覽器渲染與阻塞原理

第一部分通過performance.time這個api我們可以了解瀏覽器加載網(wǎng)頁的流程,瀏覽器邊加載html邊構(gòu)建DOM樹,當(dāng)然會有容錯和修正機制。瀏覽器解析到行內(nèi)css和內(nèi)聯(lián)css會立馬加入到構(gòu)建渲染樹,解析到外鏈css就開始加載,加載完之后也會合并到渲染樹的構(gòu)建中,最后將渲染樹和DOM做節(jié)點鏈路匹配,也叫l(wèi)ayout階段,計算每個DOM元素最終在屏幕上顯示的大小和位置。 遍歷順序為從左至右,從上到下,繪制在屏幕上,layout過程中可能會觸發(fā)頁面回流和重繪,比如某個外鏈css加載完解析之后合并構(gòu)建到渲染樹中,其中某個css改變了DOM樹種某個元素的定位(改成絕對定位)或者改變了長寬邊距等位置信息,會觸發(fā)重新layout,所以會回流reflow。重繪是比如css改變了之前的背景圖片顏色,瀏覽器會重新繪制。

會有渲染阻塞,瀏覽器刷新的頻率大概是60次/秒, 也就是說刷新一次大概時間為16ms,如果瀏覽器對每一幀的渲染工作超過了這個時間, 頁面的渲染就會出現(xiàn)卡頓的現(xiàn)象。瀏覽器內(nèi)核中有3個最主要的線程:JS線程,UI渲染線程,事件處理線程。此外還有http網(wǎng)絡(luò)線程,定時器任務(wù)線程,文件系統(tǒng)處理線程等等。

JS線程負責(zé)JS代碼解析編譯執(zhí)行,稱為主線程。常說‘瀏覽器是單線程’指的是JS主線程只能有一個,主線程執(zhí)行同步任務(wù),會阻塞UI渲染線程。JS線程核心是js引擎 (IE9+: Chakra firefox:monkey chrome:v8)。webworker可以創(chuàng)建多個js線程,但是受主線程控制,主要用于cpu密集型計算。
UI渲染線程當(dāng)然是負責(zé)構(gòu)建渲染樹,執(zhí)行頁面元素渲染。核心是渲染引擎(firefox:gecko、chrome/safari:webkit),由于JS可以操作DOM元素處理樣式等,JS主線程是執(zhí)行同步任務(wù)的,所以設(shè)計上JS引擎線程和GUI渲染線程是互斥的。 也就是說JS引擎處于運行狀態(tài)時,GUI渲染線程將處于凍結(jié)狀態(tài)。
事件處理線程,由于瀏覽器是事件驅(qū)動的,事件處理線程用來控制事件回調(diào)處理,瀏覽器觸發(fā)某個事件后會把事件回調(diào)函數(shù)放到任務(wù)隊列中,可以看下下面會提到。
其他線程統(tǒng)稱工作線程,如處理 ajax 的線程,dom事件線程、定時器線程、讀寫文件的線程等,工作線程的任務(wù)完成之后, 會推入到一個任務(wù)隊列(task queue)

總結(jié)一下,渲染阻塞有兩個方面:

js主線程執(zhí)行時間長會導(dǎo)致渲染線程阻塞,影響渲染。我們也稱為longtask
渲染線程自身阻塞,渲染時間達不到幀率60,會看起來卡頓,比如回流或者重繪等,或者css效率太低,動畫處理不合適,導(dǎo)致渲染耗時
3.請簡述下js引擎的工作原理,js是怎樣處理事件的eventloop,宏任務(wù)源tasks和微任務(wù)源jobs分別有哪些?js是如何構(gòu)造抽象語法樹(AST)的?

js引擎只執(zhí)行同步任務(wù), 異步任務(wù)會有工作線程來執(zhí)行,當(dāng)需要進行異步操作(定時器、ajax請求、dom事件注冊等), 主線程會發(fā)一個異步任務(wù)的請求, 相應(yīng)的工作線程接受請求; 當(dāng)工作線程完成工作之后, 通知主線程;主線程接收到通知之后, 會執(zhí)行一定的操作(回調(diào)函數(shù))。主線程和工作線程之間的通知機制叫做事件循環(huán)。

調(diào)用棧 (call stack): 主線程執(zhí)行時生成的調(diào)用棧
任務(wù)隊列 (task queue): 工作線程完成任務(wù)后會把消息推到一個任務(wù)隊列, 消息就是注冊時的回調(diào)函數(shù)

當(dāng)調(diào)用棧為空時, 主線程會從任務(wù)隊列里取一條消息并放入當(dāng)前的調(diào)用棧當(dāng)中執(zhí)行, 主線程會一直重復(fù)這個動作直到消息隊列為空。 這個過程就叫做事件循環(huán) (event-loop)。

關(guān)于宏任務(wù)和微任務(wù),參考?事件流、事件模型、事件循環(huán)概念理解??瀏覽器線程理解與microtask與macrotask

ES6新引入了Promise標(biāo)準(zhǔn),同時瀏覽器實現(xiàn)上多了一個microtask微任務(wù)概念。在ECMAScript中,microtask稱為jobs,macrotask可稱為task。

macrotask宏任務(wù)tasks,也就是上面說到的任務(wù)隊列的任務(wù)。執(zhí)行棧上的每個任務(wù)都屬于宏任務(wù),主線程執(zhí)行完執(zhí)行棧的任務(wù),從任務(wù)隊列取新的任務(wù)。宏任務(wù)執(zhí)行時不會中斷,會一次性執(zhí)行完,為了及時渲染數(shù)據(jù),主線程執(zhí)行完一個宏任務(wù)之后,會執(zhí)行一次渲染。

task--》渲染 --》宏任務(wù) --》渲染? .....

microtask微任務(wù)jobs,可以看成是插隊需要及時處理的任務(wù),會在當(dāng)前主線程task任務(wù)執(zhí)行后,渲染線程渲染之前,執(zhí)行完當(dāng)前積累所有的微任務(wù)。

task--》jobs --》渲染 --》宏任務(wù) --》jobs --》渲染? .....

關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端
AST 參考:程序語言進階之DSL與AST實戰(zhàn)解析

將抽象語法樹之前要先了解下NLP中文法的概率。任何一種語言,具體說就是DSL,都有自己的一套文法,用來表示這套語言的邏輯規(guī)范。不同的文法寫出來的語法表達式也不一樣。我們根據(jù)語法表達式來解析語言,就可以形成一個AST抽象語法樹。然后可以作進一步處理。我常用的是PEG解析表達式語法。可以很輕松的寫出語法的每一條產(chǎn)生式規(guī)則,來構(gòu)造生成AST。所謂AST可以理解成按照一定語法結(jié)構(gòu)組成的詞匯流,每個詞匯有特定的語法含義,比如說這是一個聲明,這個一個操作符等等。

上面這個圖是蘋果最早做的KHTML渲染引擎中的KJS(javascript引擎),他是基于AST來實現(xiàn)的JavaScript語言解析的,先通過詞法分析得到JSTokens流,然后經(jīng)過語法分析得到抽象語法樹,然后經(jīng)過字節(jié)碼生成器,轉(zhuǎn)換成字節(jié)碼。字節(jié)碼經(jīng)過JavaScript虛擬機JIT編譯成機器碼,然后執(zhí)行。這是最初的設(shè)計架構(gòu),后來蘋果公司基于此重構(gòu)出了webkit渲染引擎,google基于webkit多帶帶維護,稱為blink渲染引擎,chrome的JS引擎改造為V8引擎。參考:簡述Chromium, CEF, Webkit, JavaScriptCore, V8, Blink

舉個例子常用的babel插件的原理就是基于babylon詞法語法分析器生成抽象語法樹,將代碼文本轉(zhuǎn)換成按照特定語法組合的token流集合,然后經(jīng)過babtlon-traverse這個組件來負責(zé)處理遍歷語法樹,訪問每個token節(jié)點,通過對token的處理,可以生成我們需要的AST語法樹,然后再通過babylon-generator這個組件來做代碼生成,根據(jù)AST生成代碼。比如可以將 箭頭函數(shù) 轉(zhuǎn)換成 function函數(shù)。

瀏覽器中,通過開發(fā)者調(diào)試工具分析就能看到,下載完js腳本后,首先瀏覽器要先解析代碼=》初始化上下文環(huán)境=》執(zhí)行代碼,整個是evaluate script的過程,解析代碼的過程也是編譯js的過程所以看最前面第一步就是compile script,將js代碼編譯成字節(jié)碼(這一塊涉及到瀏覽器js引擎的優(yōu)化,v8引擎是編譯成字節(jié)碼,后面經(jīng)過JIT解析執(zhí)行(這個參考 你不知道的LLVM編譯器?可以提升效率做動態(tài)優(yōu)化), 這個類似于java、C#這些需要將源代碼編譯成中間語言,然后在虛擬機執(zhí)行,javascript編譯成字節(jié)碼后面也是在虛擬機執(zhí)行),然后就開始執(zhí)行腳本。

關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端

4.你是否考慮全面你編寫的整個函數(shù),或者整個功能的容錯性與擴展性?怎樣構(gòu)建一個組件是最合理最科學(xué)的,對于錯誤的處理是否有統(tǒng)一的方式方法?

擴展性主要是從功能上考慮,容錯性是從數(shù)據(jù)上考慮。

設(shè)計開發(fā)組件的時候首先要設(shè)計好數(shù)據(jù)模型,當(dāng)然可以和后端共同約定一個標(biāo)準(zhǔn),后面只要是這部分都用這個標(biāo)準(zhǔn)字段。后面可以對標(biāo)準(zhǔn)字段做擴展,開發(fā)時候要做容錯和數(shù)據(jù)響應(yīng)式開發(fā)。
功能這部分其實可以從基礎(chǔ)功能和擴展功能來看,基礎(chǔ)功能可以在原有組件上做根據(jù)數(shù)據(jù)來展示。擴展功能可以通過組件結(jié)合的形式來處理。

我主要考慮的是組件復(fù)用,可以將一類組件歸類,比如商品卡片,基本都是頭圖加標(biāo)題行動點,價格,按鈕。這就是最基礎(chǔ)的一個組件。擴展性可以通過數(shù)據(jù)來做響應(yīng)式的展示,比如新增一個描述,數(shù)據(jù)模型新增描述字段,有描述字段卡片上就展示描述,沒有就不展示。像點擊按鈕的加購功能可以多帶帶做成功能組件,統(tǒng)一處理,而不放在卡片上。因為這種加購?fù)綆У氖巧虡I(yè)邏輯,有很多業(yè)務(wù)邏輯要處理,獨立出來反而更利于維護和拓展。

錯誤處理我們這邊是基于組件的方式來處理,開發(fā)一個錯誤處理的功能組件,提供thenable的能力,區(qū)分不同的錯誤類型,提供統(tǒng)一埋點做監(jiān)控和記錄。

5.瀏覽器緩存的基本策略,什么時候該緩存什么時候不該緩存,以及對于控制緩存的字段的相關(guān)設(shè)置是否清楚?

參考下:HTTP協(xié)商緩存VS強緩存原理

前面介紹navigation api時候介紹了瀏覽器加載頁面的各個關(guān)鍵時間節(jié)點。和緩存相關(guān)的主要有兩部分

appcache,這部分是離線緩存,在fetchStart和domainLookupStart之間,這部分參考whatwg標(biāo)準(zhǔn)已經(jīng)棄用,建議用serviceworker。這里也不做介紹。
HTTP緩存這部分是在requestStart開始,發(fā)起資源http請求開始,這部分涉及到強緩存和協(xié)商緩存。瀏覽器對于請求過得資源會緩存下來請求的響應(yīng)數(shù)據(jù),后面請求時會先從緩存查找匹配的請求的響應(yīng)頭,如果命中強緩存(判斷cache-control和expires信息)那么直接從緩存獲取響應(yīng)數(shù)據(jù),不會再發(fā)送http請求。如果沒有命中瀏覽器會發(fā)送請求到服務(wù)器,同時會攜帶第一次請求的響應(yīng)頭的緩存相關(guān)header字段(last-modified/if-modified-since, Etag/if-none-match), 服務(wù)端根據(jù)這些請求頭判斷是否走緩存,如果走緩存,服務(wù)端會返回新的響應(yīng)頭,但不返回數(shù)據(jù),瀏覽器會更新響應(yīng)頭,從緩存拿數(shù)據(jù)。如果不走緩存,服務(wù)端就會返回新的響應(yīng)頭和數(shù)據(jù),然后瀏覽器更新緩存的數(shù)據(jù)。

-》強緩存,判斷依據(jù)是expires(http 1.0協(xié)議規(guī)定)和cache-control(http 1.1協(xié)議規(guī)定)字段,expires是絕對時間,cache-control有可選值no-cache(不使用本地緩存,走協(xié)商緩存),no-store(禁止瀏覽器緩存數(shù)據(jù),每次都是重新獲取數(shù)據(jù)),public(可以被客戶端和中間商CDN做緩存),private(只能客戶端緩存,CDN不能緩存)

-》協(xié)商緩存,用到的響應(yīng)頭字段是last-modified/if-modified-since, Etag/if-none-match,這是兩對哈,每隊/前面一個是服務(wù)端返回的response header中的字段,/后面是請求頭request攜帶的頭部字段,第一次請求資源瀏覽器會返回last-modified(最后修改時間),后面再次請求請求頭會帶上if-modified-since,當(dāng)然這個值和上次瀏覽器返回的last-modified是一樣的,然后瀏覽器判斷如果文件沒有變化,那么返回304?Not Modified http code,響應(yīng)請求頭不會攜帶last-modified字段,瀏覽器從緩存取數(shù)據(jù),也不用更新last-modified字段,如果有修改,那么響應(yīng)頭返回新的last-modified字段數(shù)據(jù),返回響應(yīng)內(nèi)容。Etag/if-none-match這一對是同樣的邏輯,不同之處是用etag標(biāo)識來判斷文件是否修改,而不是用時間,因為服務(wù)器時間可能會變的,還會收到時區(qū)的影響。還有一點是每次請求都會返回etag字段,即使沒有變化。

關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端

6.你是否可以利用面向?qū)ο蟮乃季S去抽象你的功能,你會構(gòu)建一個class(ES6)嗎?你對于前端架構(gòu)的理解?

我目前開發(fā)分情況用不同的技術(shù)框架。

如果單純開發(fā)導(dǎo)購頁面,比如一個商品列表頁面,這種為了加載性能和操作體驗,我是不考慮用框架的,也不用class,單純用自己開發(fā)的原生ES框架自己控制頁面模塊生命周期,基于函數(shù)式編程寫stateless組件。盡量減少復(fù)雜度,簡單化。
如果是開發(fā)功能性組件,我是會用面型對象的模式來做開發(fā)。面向?qū)ο蟮暮诵氖欠庋b、繼承、多態(tài)。封裝就是將具體化為抽象,抽象成class,封裝抽象出來的屬性和方法。繼承是因為抽象可以有層級,比如對異常處理,參數(shù)異常可以抽象成一類,狀態(tài)異常可以抽象成一類,參數(shù)異常和狀態(tài)異常有共通的地方,比如結(jié)構(gòu)上都會返回異常的名稱和描述,這就可以抽象一層公共父類,然后這兩個異常繼承自公共父類,這就是集成。多態(tài)也是隨著繼承而來的,比如參數(shù)異常和狀態(tài)異常都繼承了name這個屬性,都可以實現(xiàn)對應(yīng)的get方法,但是他們的實現(xiàn)結(jié)果可定是不一樣的,根據(jù)自身類的抽象來實現(xiàn),調(diào)用的時候調(diào)用同樣的方法也就有不同的表現(xiàn)。比如參數(shù)異常和狀態(tài)異常都繼承了toString的方法,在調(diào)用各自的實例的toString方法時,輸出的數(shù)據(jù)是不一樣的。另外設(shè)計的2大原則是:單一職責(zé)原則和開放封閉原則。單一職責(zé)只是抽象的類盡量保持功能專一,開閉原則指設(shè)計的時候要考慮好擴展,對修改關(guān)閉,對擴展開放。

export class RuntimeException {

    constructor(message) {
        this._message = message;
    }

    get name() {
        return "RuntimeException";
    }

    get message() {
        return this._message;
    }

    toString() {
        return this.name + ": " + this.message;
    }

}

export class IllegalStateException extends RuntimeException {

    constructor(message) {
        super(message);
    }

    get name() {
        return "IllegalStateException";
    }

}

export class InvalidArgumentException extends RuntimeException {

    constructor(message) {
        super(message);
    }

    get name() {
        return "InvalidArgumentException";
    }

}

export class NotImplementedException extends RuntimeException {

    constructor(message) {
        super(message);
    }

    get name() {
        return "NotImplementedException";
    }

}

對于前端領(lǐng)域來說,目前前端框架做掉了很多事情,搭建好項目框架之后,開發(fā)的就行就是填功能。所編寫的模塊和組件的模式也比較固定,可以根據(jù)具體情況來實現(xiàn)。

關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端

7.你會用VUE,你會用React,你讀得懂這兩個架構(gòu)的源碼嗎?你懂他倆的基本設(shè)計模式嗎?讓你去構(gòu)建一個類似的框架你如何下手?

angular

特點: 數(shù)據(jù)雙向綁定-》數(shù)據(jù)驅(qū)動開發(fā)的思想
html標(biāo)簽化的模板,模塊化思想
數(shù)據(jù)綁定,控制器,依賴注入,
服務(wù),指令,過濾器…

優(yōu)點: 比較完善規(guī)范,文檔、社區(qū)比較活躍
模塊清晰,代碼明了

缺點: 功能規(guī)范太固定,開發(fā)發(fā)揮空間小。
相對react和vue,不夠輕量化
擴展性不夠靈活

react
特點: 強大的組件化思想,任意封裝、組合
獨創(chuàng)JSX語法,virtual dom智能patch,靈活高效
輕量,易擴展,模塊清晰,代碼明了
社區(qū)生態(tài)完善,組件庫、插件庫豐富
新特性: hooks,錯誤邊界等優(yōu)化

缺點: 組件難以在復(fù)雜交互場景復(fù)用
側(cè)重于做組件,做view展示層,對于業(yè)務(wù)邏輯等封裝治理不如angular強大
JSX中html模板不夠完備和健壯,比如一些屬性變換寫法,綁定事件大小寫

vue
特點: 文檔豐富,容易上手
模板較完備,聲明式渲染,插值表達式與指令系統(tǒng),
事件處理器,修飾符,計算屬性?,簡單易用,功能強
社區(qū)生態(tài)完善,組件庫、插件庫豐富

缺點: 輕量框架使用是要結(jié)合生態(tài)插件組件使用,項目初始配置比較麻煩,
不過可以參考各種場景的標(biāo)準(zhǔn)模板配置,很多腳手架

聲明式渲染與命令式渲染:? 這個涉及到函數(shù)式編程中的一個聲明式編程和命令式編程的概念。
比如命令式編程:

let a = []
for(let i=0; i< 10; i++){
  a.push(i*10)
}

聲明式編程:

let a = []
arr.forEach(i=>{
  a.push(i*10)
})

聲明式編程隱藏了函數(shù)處理細節(jié),命令式編程則需要處理細節(jié)。

聲明式編程的好處是簡單化,易于理解,減少勞動量。比如vue中的指令綁定事件,綁定屬性都是這樣。@click,:title等等,用的時候很方便,這正是聲明式編程最直觀的好處。

關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端

8.你了解的ES6只是const、let、promise嗎?你考慮過ES6提出的真正趨勢嗎?

怎么可能,我又不是你。ES6中最常用的像變量定義這部分用let、const可以避免一些坑,異步處理可以用promise,不過我到喜歡用async/await 更簡潔好用。

還有簡寫的箭頭函數(shù),代碼看起來更清晰。
"..." 變量析構(gòu)和組裝, 函數(shù)默認值
``模板字符串,便于字符拼接;標(biāo)簽?zāi)0?功能
Object對象的擴展, for in, Object.keys
Set和Map
class和module相關(guān)

發(fā)展趨勢: 總體來說前端開發(fā)更規(guī)范,更簡單,語法更完備和成熟。支持的功能增強,開發(fā)效率提升,體驗增強。

ES6的模塊化相關(guān)支持,可以更好地支持模塊化開發(fā)。
原生支持class,面向?qū)ο蟮木幊蹋拍罡菀桌斫猓子谲浖_發(fā)和集成。
異步操作規(guī)范化,異步編程更簡單

9.你會用less,那么讓你去寫一個loader你可以嗎?

參考下:程序語言進階之DSL與AST實戰(zhàn)解析

可以的,說一下原理,需要將 .less 文件最終解析成CSS,less是一種DSL,我們可以現(xiàn)根據(jù)less預(yù)發(fā),先將其解析成AST,然后解析成CSS即可。 我推薦用PEG.js這種解析表達式語法更簡單些,只需要描述產(chǎn)生式規(guī)則即可。也可以自己根據(jù)LESS預(yù)發(fā)來寫正則表達來匹配規(guī)則,然后轉(zhuǎn)換成css。比較常用的是PostCSS,處理流程如下:參考官方文檔

PostCSS的處理流程也是經(jīng)過詞法解析語法分析,將讀取到的文件字符轉(zhuǎn)化成詞匯流tokens,根據(jù)語法分析,根據(jù)less的語法,解析成一個AST。

source string → tokens → AST

核心組件有:

詞法分析器 Tokenizer (?lib/tokenize.es6?)
語法分析器 Parser (?lib/parse.es6,?lib/parser.es6?)
插件處理器 Processor (?lib/processor.es6?)
代碼生成器 Stringifier (?lib/stringify.es6,?lib/stringifier.es6?)

10.webpack你也會用,你了解其中原理嗎?你知道分析打包依賴的過程嗎?你知道tree-shaking是如何干掉無用重復(fù)的代碼的嗎?

大家之前應(yīng)該用過gulp,grunt這種代碼打包工具,定義不同的打包任務(wù)和打包流程。我用的比較多的rollup這個打包工具,配置起來比較簡單些。

webpack也是用來做代碼打包,可以做代碼分析,拆分,混淆,壓縮等等,基于他的插件擴展機制可以做很多事情。分析webpack的原理,可以先從webpack配置文件說起。參考:webpack編譯代碼原理介紹?用webpack4和一些插件提升代碼編譯速度

首先作為打包工具,要定義打包的輸入entry和輸出output;然后是定義webpack要用到的module,比如babel js loader, cssloader等等。執(zhí)行編譯具體的流程是:

加載webpack配置文件 --》 根據(jù)配置初始化編譯器compiler --》找到入口,根據(jù)loader配置開始編譯入口文件以及層層依賴 --》編譯完成之后,可以得到所有編譯過的文件和依賴關(guān)系結(jié)構(gòu) --》根據(jù)依賴關(guān)系將模塊組裝成一個個包含多個模塊的chunk,然后根據(jù)配置寫到輸出文件。

webpack構(gòu)建流程可分為以下三大階段。

初始化:啟動構(gòu)建,讀取與合并配置參數(shù),加載plugin,實例化Compiler
編譯:從Entry出發(fā),針對每個Module串行調(diào)用對應(yīng)的Loader去翻譯文件中的內(nèi)容,再找到該Module依賴的Module,遞歸的進行編譯處理
輸出:將編譯后的Module組合成Chunk,將Chunk轉(zhuǎn)換成文件,輸出到文件系統(tǒng)中

分析依賴是在編譯過程中完成的,從入口查找依賴,最后形成依賴關(guān)系。 為了提高效率,可以記錄分析過的依賴,這樣下次遇到同樣的模塊就不用再分析,直接引用編譯過的依賴就可以了。

tree-shaking的名字原理一樣,就是搖一搖大樹,落下來的葉子都是冗余的部分。Tree-shaking 較早由 Rich_Harris 的 rollup 實現(xiàn),后來,webpack2 也增加了tree-shaking 的功能。其實在更早,google closure compiler 也做過類似的事情。三個工具的效果和使用各不相同,使用方法可以通過官網(wǎng)文檔去了解。

tree shaking的目的是去掉無用代碼,減少代碼體積。其實對于編譯的編程語言對應(yīng)的編譯器基本都有判斷哪些代碼不會影響輸出,從而在編譯時移除這些代碼的功能,稱為DCE(dead code elimination)。tree shaking 是DCE的一種實現(xiàn),傳統(tǒng)的是消除沒有引用不會執(zhí)行的代碼,tree shaking 主要是要消除沒有用的代碼。

Dead Code 一般具有以下幾個特征

?代碼不會被執(zhí)行,不可到達

?代碼執(zhí)行的結(jié)果不會被用到

?代碼只會影響死變量(只寫不讀)

在前端代碼打包處理中,最終都會有個代碼壓縮混淆的環(huán)節(jié),這個環(huán)節(jié)其實會完成DCE的工作,會將這些dead code移除。

但是uglify代碼是只是單個單個文件處理,并不能分析出這個代碼有沒有被其他文件用到,當(dāng)然也不會對這些為被調(diào)用的函數(shù)做處理,如上圖uglify就不會去除沒用到的get函數(shù),所以就需要tree shaking。tree shaking是有限制的,只能消除函數(shù)和import/export的變量,不會處理import/export的class(因為javascript動態(tài)語言特性使得分析比較困難,可能導(dǎo)致以外的錯誤,side effect比較大), 對于純函數(shù)處理效果較好。
關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端

11.你真的熟練使用css嗎,那你知道position有幾個屬性嗎

具體參考https://github.com/wintercn/b...

static:無特殊定位,對象遵循正常文檔流。top,right,bottom,left等屬性不會被應(yīng)用。
relative:對象遵循正常文檔流,但將依據(jù)top,right,bottom,left等屬性在正常文檔流中偏移位置,相對定位相對的是它原本在文檔流中的位置而進行的偏移。而其層疊通過z-index屬性定義。占據(jù)的文檔空間不會隨 top / right / left / bottom 等屬性的偏移而發(fā)生變動,也就是說它后面的元素是依據(jù)( top / left / right / bottom 等屬性生效之前)進行的定位,這點一定要理解。
absolute:對象脫離正常文檔流,使用top,right,bottom,left等屬性進行絕對定位。而其層疊通過z-index屬性定義。使用absoulte或fixed定位的話,必須指定 left、right、 top、 bottom 屬性中的至少一個,否則left/right/top/bottom屬性會使用它們的默認值 auto ,這將導(dǎo)致對象遵從正常的HTML布局規(guī)則,在前一個對象之后立即被呈遞,簡單講就是都變成relative,會占用文檔空間,這點非常重要,很多人使用absolute定位后發(fā)現(xiàn)沒有脫離文檔流就是這個原因。
fixed:對象脫離正常文檔流,使用top,right,bottom,left等屬性以窗口為參考點進行定位,當(dāng)出現(xiàn)滾動條時,對象不會隨著滾動。而其層疊通過z-index屬性定義。
sticky:?The element is positioned according to the normal flow of the document, and then offset relative to its?nearest scrolling ancestor?and?containing block?(nearest block-level ancestor), including table-related elements, based on the values of?top,?right,?bottom, and?left. The offset does not affect the position of any other elements.This value always creates a new?stacking context. Note that a sticky element "sticks" to its nearest ancestor that has a "scrolling mechanism" (created when?overflow?is?hidden,?scroll,?auto, or?overlay), even if that ancestor isn"t the nearest actually scrolling ancestor. This effectively inhibits any "sticky" behavior (see the?Github issue on W3C CSSWG).

absolute就只能根據(jù)祖先類元素(父類以上)進行定位,而這個祖先類還必須是以postion非static方式定位的, 舉個例子,a元素使用absoulte定位,它會從父類開始找起,尋找以position非static方式定位的祖先類元素(注意,一定要是直系祖先才算哦~),直到標(biāo)簽為止,這里還需要注意的是,relative和static方式在最外層時是以標(biāo)簽為定位原點的,而absoulte方式在無父級是position非static定位時是以作為原點定位。

參考:?position屬性

關(guān)于Layout and the containing block,看下官方介紹的contain block,另外相關(guān)的點是 BFC:如何創(chuàng)建塊級格式化上下文(block formatting context),BFC有什么用

12 前端動畫渲染機制了解嗎?硬件加速原理?

參考:瀏覽器渲染流水線解析與網(wǎng)頁動畫性能優(yōu)化

動畫可以看做是一個連續(xù)的幀序列的組合。我們把網(wǎng)頁的動畫分成兩大類 —— 一類是合成器動畫,一類是非合成器動畫(UC 內(nèi)部也將其稱為內(nèi)核動畫或者 Blink Animation,雖然這不是 Chrome 官方的術(shù)語)。

合成器動畫顧名思義,動畫的每一幀都是由 Layer Compositor 生成并輸出的,合成器自身驅(qū)動著整個動畫的運行,在動畫的過程中,不需要新的 Main Frame 輸入;
非合成器動畫,每一幀都是由 Blink 生成,都需要產(chǎn)生一個新的 Main Frame;

合成器動畫又可以分為兩類:

合成器本身觸發(fā)并運行的,比如最常見的網(wǎng)頁慣性滾動,包括整個網(wǎng)頁或者某個頁內(nèi)可滾動元素的滾動;
Blink 觸發(fā)然后交由合成器運行,比如說傳統(tǒng)的 CSS Translation 或者新的 Animation API,如果它們觸發(fā)的動畫經(jīng)由 Blink 判斷可以交由合成器運行;

Blink 觸發(fā)的動畫,如果是 Transform 和 Opacity 屬性的動畫基本上都可以由合成器運行,因為它們沒有改變圖層的內(nèi)容。不過即使可以交由合成器運行,它們也需要產(chǎn)生一個新的 Main Frame 提交給合成器來觸發(fā)這個動畫,如果這個 Main Frame 包含了大量的圖層變更,也會導(dǎo)致觸發(fā)的瞬間卡頓,頁端事先對圖層結(jié)構(gòu)進行優(yōu)化可以避免這個問題。

非合成器動畫也可以分為兩類:

使用 CSS Translation 或者 Animation API 創(chuàng)建的動畫,但是無法由合成器運行;
使用 Timer 或者 rAF 由 JS 驅(qū)動的動畫,比較典型的就是 Canvas/WebGL 游戲,這種動畫實際上是由頁端自己定義的,瀏覽器本身并沒有對應(yīng)的動畫的概念,也就是說瀏覽器本身是不知道這個動畫什么時候開始,是否正在運行,什么時候結(jié)束,這些完全是頁端自己的內(nèi)部邏輯;

合成器動畫和非合成器動畫在渲染流水線上有較大的差異,后者更復(fù)雜,流水線更長。上面四種動畫的分類,按渲染流水線的復(fù)雜程度和理論性能排列(復(fù)雜程度由低到高,理論性能由高到低):

合成器本身觸發(fā)并運行的動畫;
Blink 觸發(fā),合成器運行的動畫;
Blink 觸發(fā),無法由合成器運行的動畫;
由 Timer/rAF 驅(qū)動的 JS 動畫;

開啟硬件加速的方法很多,比如transform:?translate3d(0,0,0); 加了之后,在chrome開發(fā)者工具中的layer欄目下可以看到多了一層 composition layer,同時給出了理由描述是開啟了3D transform,這個元素就放入了Composited Layer中托管,其動畫效果都是在多帶帶一個圖形層上面處理,不會影響其它層。

什么情況下能使元素獲得自己的層?雖然 Chrome 的啟發(fā)式方法(heuristic)隨著時間在不斷發(fā)展進步,但是從目前來說,滿足以下任意情況便會創(chuàng)建層:

3D 或透視變換(perspective transform) CSS 屬性
使用加速視頻解碼的 元素
擁有 3D (WebGL) 上下文或加速的 2D 上下文的 元素
混合插件(如 Flash)
對自己的 opacity 做 CSS 動畫或使用一個動畫 webkit 變換的元素
擁有加速 CSS 過濾器的元素
元素有一個包含復(fù)合層的后代節(jié)點(換句話說,就是一個元素擁有一個子元素,該子元素在自己的層里)
元素有一個 z-index 較低且包含一個復(fù)合層的兄弟元素(換句話說就是該元素在復(fù)合層上面渲染)

使用3D硬件加速提升動畫性能時,最好給元素增加一個z-index屬性,人為干擾復(fù)合層的排序,可以有效減少chrome創(chuàng)建不必要的復(fù)合層,提升渲染性能,移動端優(yōu)化效果尤為明顯。

關(guān)于層的介紹:gpu-accelerated-compositing-in-chrome

理解CSS animations 和 transitions的性能問題與動畫調(diào)試

關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端

13.你了解js的數(shù)據(jù)結(jié)構(gòu)嗎?基本數(shù)據(jù)類型有哪些?復(fù)雜數(shù)據(jù)類型有哪些?在內(nèi)存是如何表現(xiàn)的?

參考MDN,最新的 ECMAScript 標(biāo)準(zhǔn)定義了 7 種數(shù)據(jù)類型:

6 種原始類型:
Boolean
Null
Undefined
Number
String
Symbol?(ECMAScript 6 新定義)
和?Object

除 Object 以外的所有類型都是不可變的(值本身無法被改變)。例如,與 C 語言不同,JavaScript 中字符串是不可變的。JavaScript 中對字符串的操作一定返回了一個新字符串,原始字符串并沒有被改變。

標(biāo)準(zhǔn)的" 對象, 和函數(shù)【復(fù)雜數(shù)據(jù)類型】

日期:內(nèi)建的?Date?對象

數(shù)組和類型數(shù)組:

數(shù)組是一種使用整數(shù)作為鍵(integer-key-ed)屬性和長度(length)屬性之間關(guān)聯(lián)的常規(guī)對象。此外,數(shù)組對象還繼承了 Array.prototype 的一些操作數(shù)組的便捷方法。例如,?indexOf?(搜索數(shù)組中的一個值) or?push?(向數(shù)組中添加一個元素),等等。?這使得數(shù)組是表示列表或集合的最優(yōu)選擇。

類型數(shù)組(Typed Arrays)是ECMAScript Edition 6中新定義的 JavaScript 內(nèi)建對象,提供了一個基本的二進制數(shù)據(jù)緩沖區(qū)的類數(shù)組視圖。

集合對象Map、WeakMap、Set、WeakSet:這些數(shù)據(jù)結(jié)構(gòu)把對象的引用當(dāng)作鍵,其在ECMAScript第6版中有介紹。當(dāng)?Map?和?WeakMap?把一個值和對象關(guān)聯(lián)起來的時候,?Set?和?WeakSet?表示一組對象。 Map和WeakMaps之間的差別在于,在前者中,對象鍵是可枚舉的。

結(jié)構(gòu)化數(shù)據(jù)JSON:JSON (JavaScript Object Notation) 是一種輕量級的數(shù)據(jù)交換格式

參考:標(biāo)準(zhǔn)全局內(nèi)置對象

兩種類型:

1.???ECMAScript變量包含兩種不同類型的值:基本類型值、引用類型值;

2.???基本類型值:指的是保存在棧內(nèi)存中的簡單數(shù)據(jù)段;

3.???引用類型值:指的是那些保存在堆內(nèi)存中的對象,意思是,變量中保存的實際上只是一個指針,這個指針執(zhí)行內(nèi)存中的另一個位置,由該位置保存對象;

兩種訪問方式:

4.???基本類型值:按值訪問,操作的是他們實際保存的值;

5.???引用類型值:按引用訪問,當(dāng)查詢時,我們需要先從棧中讀取內(nèi)存地址,然后再順藤摸瓜地找到保存在堆內(nèi)存中的值;

數(shù)據(jù)復(fù)制

基本類型變量的復(fù)制:從一個變量向一個變量復(fù)制時,會在棧中創(chuàng)建一個新值,然后把值復(fù)制到為新變量分配的位置上;
引用類型變量的復(fù)制:復(fù)制的是存儲在棧中的指針,將指針復(fù)制到棧中未新變量分配的空間中,而這個指針副本和原指針執(zhí)行存儲在堆中的同一個對象;復(fù)制操作結(jié)束后,兩個變量實際上將引用同一個對象;因此改變其中的一個,將影響另一個;

三種變量類型檢測

1.???Typeof操作符是檢測基本類型的最佳工具;

2.???如果變量值是null或者對象,typeof?將返回“object”;結(jié)合null == null 來判斷

3.???Instanceof用于檢測引用類型,可以檢測到具體的,它是什么類型的實例;

4.???如果變量是給定引用類型的實例,instanceof操作符會返回true;

Object.prototype.toString.call(xx) 來打印原型判斷類型

關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端

14.你可以用js去實現(xiàn)一個單向、雙向、循環(huán)鏈表嗎?你可以實現(xiàn)查找、插入、刪除操作嗎?

可以在這里試一下:在線編程環(huán)境

鏈表:

插入鏈表節(jié)點:

刪除鏈表節(jié)點:

雙向鏈表:

循環(huán)鏈表:

下面給一個最簡單的單項鏈表示例:

/**
** 先創(chuàng)建一個節(jié)點類,記錄當(dāng)前數(shù)據(jù),和下個節(jié)點,如果是雙向鏈表,就包含prev
** prev: 對上個節(jié)點的引用
** next: 對下個節(jié)點的應(yīng)用
**/
class Node{
  constructor(data){
    this.data = data;
    this.next = null;
  }
}
/**
** 創(chuàng)建鏈表,head是鏈表中的一個起始節(jié)點,關(guān)于單項鏈表,雙向鏈表和循環(huán)鏈表參考文章介紹
** find: 找到數(shù)據(jù)所在的節(jié)點,這里是示例,其實應(yīng)該有個唯一標(biāo)識
** insert: 在指定節(jié)點后面插入節(jié)點
**/
class LinkTable{
  constructor(data){
    this.head = null;
    this.end = null;
    if(data){
      this.head = new Node(data)
    }
  }
  find(data){
    let start = this.head;
    while(start.data != data){
      start = start.next;
    }
    return start;
  }
  insert(data,node){
    let nod = new Node(data);
    nod.next = node.next;
    item.next = nod;
  }
}

關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端

14.你了解基本常見算法嗎?快速排序?qū)懸粋€?要是限制空間利用你該如何寫?

快速排序:

(1)在數(shù)據(jù)集之中,選擇一個元素作為"基準(zhǔn)"(pivot)。

(2)所有小于"基準(zhǔn)"的元素,都移到"基準(zhǔn)"的左邊;所有大于"基準(zhǔn)"的元素,都移到"基準(zhǔn)"的右邊。

(3)對"基準(zhǔn)"左邊和右邊的兩個子集,不斷重復(fù)第一步和第二步,直到所有子集只剩下一個元素為止。

選擇排序:

(1)首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置

(2)再從剩余未排序元素中繼續(xù)尋找最小(大)元素,然后放到已排序序列的末尾

(3)直到所有都排序

冒泡排序:

比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
對每一對相鄰元素作同樣的工作,從開始第一對到結(jié)尾的最后一對。在這一點,最后的元素應(yīng)該會是最大的數(shù)。
針對所有的元素重復(fù)以上的步驟,除了最后一個。
持續(xù)每次對越來越少的元素重復(fù)上面的步驟,直到?jīng)]有任何一對數(shù)字需要比較。

直接插入排序:

(1)將待排序數(shù)組取一個數(shù)值插入到已排序數(shù)組中合適的位置

(2)重復(fù)取數(shù)據(jù),直到所有數(shù)據(jù)取完

15.你了解貪心算法、動態(tài)規(guī)劃、分治算法、回溯算法等常見的算法嗎?

貪心算法

?所謂貪心算法是指,在對問題求解時,總是做出在當(dāng)前看來是最好的選擇。也就是說,不從整體最優(yōu)上加以考慮,他所做出的僅是在某種意義上的局部最優(yōu)解。
?????貪心算法沒有固定的算法框架,算法設(shè)計的關(guān)鍵是貪心策略的選擇。必須注意的是,貪心算法不是對所有問題都能得到整體最優(yōu)解,選擇的貪心策略必須具備無后效性,即某個狀態(tài)以后的過程不會影響以前的狀態(tài),只與當(dāng)前狀態(tài)有關(guān)。
????所以對所采用的貪心策略一定要仔細分析其是否滿足無后效性。
貪心算法的基本思路:
??? 1.建立數(shù)學(xué)模型來描述問題。
??? 2.把求解的問題分成若干個子問題。
??? 3.對每一子問題求解,得到子問題的局部最優(yōu)解。
??? 4.把子問題的解局部最優(yōu)解合成原來解問題的一個解。

動態(tài)規(guī)劃算法

動態(tài)規(guī)劃過程是:每次決策依賴于當(dāng)前狀態(tài),又隨即引起狀態(tài)的轉(zhuǎn)移。一個決策序列就是在變化的狀態(tài)中產(chǎn)生出來的,所以,這種多階段最優(yōu)化決策解決問題的過程就稱為動態(tài)規(guī)劃。

?? ?基本思想與分治法類似,也是將待求解的問題分解為若干個子問題(階段),按順序求解子階段,前一子問題的解,為后一子問題的求解提供了有用的信息。在求解任一子問題時,列出各種可能的局部解,通過決策保留那些有可能達到最優(yōu)的局部解,丟棄其他局部解。依次解決各子問題,最后一個子問題就是初始問題的解。

?? ?由于動態(tài)規(guī)劃解決的問題多數(shù)有重疊子問題這個特點,為減少重復(fù)計算,對每一個子問題只解一次,將其不同階段的不同狀態(tài)保存在一個二維數(shù)組中。

?? ?與分治法最大的差別是:適合于用動態(tài)規(guī)劃法求解的問題,經(jīng)分解后得到的子問題往往不是互相獨立的(即下一個子階段的求解是建立在上一個子階段的解的基礎(chǔ)上,進行進一步的求解)。

能采用動態(tài)規(guī)劃求解的問題的一般要具有3個性質(zhì):

??? (1) 最優(yōu)化原理:如果問題的最優(yōu)解所包含的子問題的解也是最優(yōu)的,就稱該問題具有最優(yōu)子結(jié)構(gòu),即滿足最優(yōu)化原理。

??? (2) 無后效性:即某階段狀態(tài)一旦確定,就不受這個狀態(tài)以后決策的影響。也就是說,某狀態(tài)以后的過程不會影響以前的狀態(tài),只與當(dāng)前狀態(tài)有關(guān)。

?? (3)有重疊子問題:即子問題之間是不獨立的,一個子問題在下一階段決策中可能被多次使用到。(該性質(zhì)并不是動態(tài)規(guī)劃適用的必要條件,但是如果沒有這條性質(zhì),動態(tài)規(guī)劃算法同其他算法相比就不具備優(yōu)勢)

分治算法

分治法的設(shè)計思想是:將一個難以直接解決的大問題,分割成一些規(guī)模較小的相同問題,以便各個擊破,分而治之。

分治策略是:對于一個規(guī)模為n的問題,若該問題可以容易地解決(比如說規(guī)模n較小)則直接解決,否則將其分解為k個規(guī)模較小的子問題,這些子問題互相獨立且與原問題形式相同,遞歸地解這些子問題,然后將各子問題的解合并得到原問題的解。這種算法設(shè)計策略叫做分治法。

分治法所能解決的問題一般具有以下幾個特征:

1) 該問題的規(guī)模縮小到一定的程度就可以容易地解決

2) 該問題可以分解為若干個規(guī)模較小的相同問題,即該問題具有最優(yōu)子結(jié)構(gòu)性質(zhì)。

3) 利用該問題分解出的子問題的解可以合并為該問題的解;

4) 該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子子問題。

回溯法

在包含問題的所有解的解空間樹中,按照深度優(yōu)先搜索的策略,從根結(jié)點出發(fā)深度探索解空間樹。當(dāng)探索到某一結(jié)點時,要先判斷該結(jié)點是否包含問題的解,如果包含,就從該結(jié)點出發(fā)繼續(xù)探索下去,如果該結(jié)點不包含問題的解,則逐層向其祖先結(jié)點回溯。(其實回溯法就是對隱式圖的深度優(yōu)先搜索算法)

分支限界法

類似于回溯法,也是一種在問題的解空間樹T上搜索問題解的算法。但在一般情況下,分支限界法與回溯法的求解目標(biāo)不同。回溯法的求解目標(biāo)是找出T中滿足約束條件的所有解,而分支限界法的求解目標(biāo)則是找出滿足約束條件的一個解,或是在滿足約束條件的解中找出使某一目標(biāo)函數(shù)值達到極大或極小的解,即在某種意義下的最優(yōu)解。

由于求解目標(biāo)不同,導(dǎo)致分支限界法與回溯法在解空間樹T上的搜索方式也不相同。回溯法以深度優(yōu)先的方式搜索解空間樹T,而分支限界法則以廣度優(yōu)先或以最小耗費優(yōu)先的方式搜索解空間樹T。

16.你是如何理解前端架構(gòu)的?你了解持續(xù)集成嗎?

架構(gòu),我理解主要做:系統(tǒng)分解、服務(wù)分層的工作。

持續(xù)集成?(Continuous integration,簡稱CI)。項目是一個迭代一個迭代快速開發(fā),每個迭代開發(fā)不同的feature,所有的feature合在一起構(gòu)成完整的功能。

持續(xù)集成的目的,就是讓產(chǎn)品可以快速迭代,同時還能保持高質(zhì)量。它的核心措施是,代碼集成到主干之前,必須通過自動化測試。只要有一個測試用例失敗,就不能集成。

Martin Fowler說過,"持續(xù)集成并不能消除Bug,而是讓它們非常容易發(fā)現(xiàn)和改正。"

與持續(xù)集成相關(guān)的,還有兩個概念,分別是持續(xù)交付和持續(xù)部署。

17.你了解基本的設(shè)計模式嗎?舉例單例模式、策略模式、代理模式、迭代模式、發(fā)布訂閱模式。。。?

設(shè)計模式(Design pattern)代表了最佳的實踐,通常被有經(jīng)驗的面向?qū)ο蟮能浖_發(fā)人員所采用。設(shè)計模式是軟件開發(fā)人員在軟件開發(fā)過程中面臨的一般問題的解決方案。

單例模式:

單例模式(Singleton Pattern)是 Java 中最簡單的設(shè)計模式之一。這種類型的設(shè)計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式。

這種模式涉及到一個單一的類,該類負責(zé)創(chuàng)建自己的對象,同時確保只有單個對象被創(chuàng)建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。

注意:

1、單例類只能有一個實例。
2、單例類必須自己創(chuàng)建自己的唯一實例。
3、單例類必須給所有其他對象提供這一實例。

策略模式

在策略模式(Strategy Pattern)中,一個類的行為或其算法可以在運行時更改。這種類型的設(shè)計模式屬于行為型模式。

在策略模式中,我們創(chuàng)建表示各種策略的對象和一個行為隨著策略對象改變而改變的 context 對象。策略對象改變 context 對象的執(zhí)行算法。

很好理解,比如上面給的一個異常處理的代碼,寫個簡單的示例。

export class RuntimeException {

    constructor(message) {
        this._message = message;
    }

    get name() {
        return "RuntimeException";
    }

    get message() {
        return this._message;
    }

    toString() {
        return this.name + ": " + this.message;
    }

}

export class IllegalStateException extends RuntimeException {

    constructor(message) {
        super(message);
    }

    get name() {
        return "IllegalStateException";
    }

}

export class InvalidArgumentException extends RuntimeException {

    constructor(message) {
        super(message);
    }

    get name() {
        return "InvalidArgumentException";
    }

}

export class NotImplementedException extends RuntimeException {

    constructor(message) {
        super(message);
    }

    get name() {
        return "NotImplementedException";
    }

}

export function funcWrapper(args){
    try{
      if(!args) throw new InvalidArgumentException("args undefined")
      if(args == 1) throw new IllegalStateException("args illegal")
    }catch(e){
        console.log(e.toString())
    }
}

瀏覽器可以跑下結(jié)果看看:

這就是策略模式,不同的情況,輸出的結(jié)果是不一樣的。

18.寫一個事件監(jiān)聽函數(shù)唄?實現(xiàn)once、on、remove、emit功能

19.node.js的實現(xiàn)層是什么?

20.node的事件循環(huán)機制是怎樣的?node的child_process模塊有幾個api,分別的作用是什么?

22.http1.0與1.1協(xié)議的區(qū)別?node是如何實現(xiàn)http模塊的?

25.nginx相關(guān)配置了解過嗎?

27.小程序架構(gòu)

28.vue v-model 語法糖?vue push式更新?vue computed和watch的區(qū)別?

29.redux dispatch一個action之后的更新過程
connect的時候出于性能優(yōu)化的考慮做了一層淺比較。

30.假設(shè)頁面有多個模塊,每個模塊都用到了getUser方法獲取用戶信息,怎么設(shè)計通用的getUser避免發(fā)出多次請求。
這個是一個朋友給的網(wǎng)易考拉前端的面試題,朋友給了2個解法:

監(jiān)聽者模式,監(jiān)聽getUser事件,第一次注冊監(jiān)聽事件時發(fā)出請求,待請求數(shù)據(jù)回來,執(zhí)行所有回調(diào)。通過事件監(jiān)聽解耦。

基于promise,getUser方法提供一個thenable的能力,返回一個promise對象,在Promise中將resolve維護在一個resolveList列表中,其實和事件監(jiān)聽中的事件列表類似。第一次調(diào)用時發(fā)出請求,請求回來后調(diào)用resolveList列表中所有resolve。

個人感覺基于promise的方法比事件監(jiān)聽模式更優(yōu),本來就是一步的操作返回的也是一個Promise,更符合編碼邏輯。

說到最后,結(jié)合朋友的面試分享一下:
朋友說網(wǎng)易考拉前端的面試官姿態(tài)比較高,一種專橫跋扈的感覺,沒有耐心,固步自封,整體面試體驗比較差,而且面試官都是比較自以為是那種。朋友說有個面試官明顯沒準(zhǔn)備,邊問邊看簡歷,沒有重點和主線,然后讓他提問2個面試官不知道的問題,結(jié)果他誰便說了2個,面試官真的不知道,場面很尷尬。而且有幾個面試官在面試中還說錯了一些技術(shù)知識點。整體感覺面試官問的問題都是比較分散,很隨意,也反映出網(wǎng)易考拉前端的技術(shù)基礎(chǔ)建設(shè)也是比較差勁的,技術(shù)主管只關(guān)注業(yè)務(wù)實現(xiàn),對于技術(shù)體系建設(shè),技術(shù)規(guī)劃設(shè)計都沒有概念,這種團隊的技術(shù)氛圍可想而知。最后朋友說他問了那個技術(shù)主管對于技術(shù)體系建設(shè)和規(guī)劃是什么?怎么支撐業(yè)務(wù)發(fā)展?結(jié)果也沒說什么。
其實可以考慮阿里、騰訊這種大公司,面試體驗絕對不一樣,技術(shù)體系建設(shè),知識面廣度和深度,不是在一個檔次的。能去大廠還是考慮大廠,畢竟大廠是有真正的大牛在。

本文總結(jié)了前端老司機經(jīng)常問題的一些問題并結(jié)合個人總結(jié)給出了比較詳盡的答案。
關(guān)于知識點原理和詳細,參考講堂的視頻教程:前端增長-重新定義大前端
課程知識在不斷更新,本片內(nèi)容也逐步更新

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/105658.html

相關(guān)文章

  • 校招社招必備核心前端面試問題詳細解答

    摘要:本文總結(jié)了前端老司機經(jīng)常問題的一些問題并結(jié)合個人總結(jié)給出了比較詳盡的答案。網(wǎng)易阿里騰訊校招社招必備知識點。此外還有網(wǎng)絡(luò)線程,定時器任務(wù)線程,文件系統(tǒng)處理線程等等。線程核心是引擎。主線程和工作線程之間的通知機制叫做事件循環(huán)。 showImg(https://segmentfault.com/img/bVbu4aB?w=300&h=208); 本文總結(jié)了前端老司機經(jīng)常問題的一些問題并結(jié)合個...

    Rango 評論0 收藏0
  • 校招社招必備核心前端面試問題詳細解答

    摘要:本文總結(jié)了前端老司機經(jīng)常問題的一些問題并結(jié)合個人總結(jié)給出了比較詳盡的答案。網(wǎng)易阿里騰訊校招社招必備知識點。此外還有網(wǎng)絡(luò)線程,定時器任務(wù)線程,文件系統(tǒng)處理線程等等。線程核心是引擎。主線程和工作線程之間的通知機制叫做事件循環(huán)。 showImg(https://segmentfault.com/img/bVbu4aB?w=300&h=208); 本文總結(jié)了前端老司機經(jīng)常問題的一些問題并結(jié)合個...

    DevTalking 評論0 收藏0
  • 前端工程師手冊】JavaScript之閉包

    摘要:閉包確實是一個說爛了的概念,校招社招都會被問到,今天總結(jié)一番。先下定義,閉包是函數(shù)和該函數(shù)的詞法作用域的組合。在這個栗子里,函數(shù)以及它對變量的引用就構(gòu)成了閉包。閉包和作用域?qū)τ陂]包和作用域的關(guān)系,我的理解是閉包其實就是作用域的延伸。 閉包確實是一個說爛了的概念,校招社招都會被問到,今天總結(jié)一番。先下定義,閉包是函數(shù)和該函數(shù)的詞法作用域的組合。其實這個定義是比較教條的,可以直白的理解為閉...

    CarlBenjamin 評論0 收藏0
  • "雙非"應(yīng)屆生校招如何獲得大廠青睞?(內(nèi)附前端大廠面經(jīng)+技術(shù)崗超全求職攻略)

    摘要:拿到秋招的同學(xué),如確定入職需與用人單位簽署三方協(xié)議,以保證雙方的利益不受損失。當(dāng)然每個崗位所要求的側(cè)重點不同,但卻百變不離其宗。方法論要想達成某個目標(biāo)都有其特定的方法論,學(xué)習(xí)技術(shù)也不例外,掌握適當(dāng)?shù)膶W(xué)習(xí)方法才能事半功倍。 寫在前面的話 筆者從17年的2月份開始準(zhǔn)備春招,其中遇到不少坑,也意識到自己走過的彎路。故寫了這篇文章總結(jié)一番,本文適合主動學(xué)習(xí)的,對自己要學(xué)的課程不明確的,對面試有...

    jeffrey_up 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<