前端面試梳理(一)

備戰秋招,複習基礎。若有錯誤,歡迎批評指正,共同進步!javascript

寫在最前

整理自本身的面試經驗+網絡資料css

部分資料參考自網絡,在具體內容前均有標出~感恩你們~html

因爲篇幅緣由,拆成兩篇~前端面試梳理(二)前端

電話面試

實話實說!保持自信!要有邏輯!vue

  • 自我介紹 3分鐘做用,講清重點經歷。html5

    完結話術:...以上就是個人我的介紹。java

  • 簡歷相關 要熟!會檢查真實性!node

  • 專業技術react

    是否具有專業技能jquery

    對工做的見解

    職業規劃

    員工穩定性

  • 對公司的瞭解 尤爲是對應崗位的業務。提早準備,列出可能的問題。

  • 興趣愛好 儘可能與工做相關

  • 反問建議 下一步招聘流程

  • 感謝HR!!!

  • 話術:……回到您剛說的問題上

計算機基礎

常見概念

JSON: 一種JS對象表示法的數據格式。能夠表簡單值(不支持Undefined)、對象(無序鍵值對)、數組(有序值列表)。不支持變量、函數或對象實例。

MIME:多用途互聯網郵件擴展類型。

Fiber:一種編程思想。任務拆分和協同。當進程阻塞時,任務分割、異步調用、緩存策略

DN:域名,因特網上某一計算機組的名稱。如 baidu.com

DNS:域名系統,將域名和IP一一映射

IP:互聯網協議地址,是用戶上網的數字標籤

http:超文本傳輸協議

href:指定超連接目標的URL

URL:統一資源定位符。即網址http://www.baidu.com (服務器名 www)(網站名 www.baidu.com)

servlet:java提供的用於開發web服務器應用程序的一個組件。jsp是servlet的一種擴展。

cdn:內容分發網絡。CDN是構建在現有網絡基礎之上的智能虛擬網絡,依靠部署在各地的邊緣服務器,經過中心平臺的負載均衡、內容分發、調度等功能模塊,使用戶就近獲取所需內容,下降網絡擁塞,提升用戶訪問響應速度和命中率。CDN的關鍵技術主要有內容存儲和分發技術。

restful:URL定位資源,用HTTP動詞(GET,POST,DELETE,DETC)描述操做。

1. 用名詞定義接口名,用請求類型區分操做。
2. 用HTTP Status Code傳遞Server的狀態信息。
複製代碼

點擊一個Url以後

1 DNS解析
2 http請求
3 TCP三次握手
4 數據傳輸
5 渲染文檔
複製代碼

url中的#和?

參考資料:URL 連接中 井號#、問號?、鏈接符& 分別有什麼做用?

參考資料:VUE.js中訪問地址的url帶有#的問題

1 ?+任意參數 實現不一樣參數值生成不一樣頁面或返回不一樣結果 ?size=100
2 & 鏈接符,不一樣參數的間隔符,通常與問號結合使用。?size=100&time=20171120
3 # Hash 表明網頁中的一個位置。其右面的字符,就是該位置的標識符。#print
    爲網頁位置指定標識符,有兩個方法。一是使用錨點,好比<a name="print"></a>,二是使用id屬性,好比<div id="print" >
    HTTP請求不包括#。
    單單改變#後的部分,瀏覽器只會滾動到相應位置,不會從新加載網頁。
    每一次改變#後的部分,都會在瀏覽器的訪問歷史中增長一個記錄,使用"後退"按鈕,就能夠回到上一個位置。
    window.location.hash這個屬性可讀可寫。讀取時,能夠用來判斷網頁狀態是否改變;寫入時,則會在不重載網頁的前提下,創造一條訪問歷史記錄。
    onhashchange事件,當#值發生變化時,就會觸發這個事件。
4 vue中的#  VUE默認使用HASH模式
    HASH模式:
    HASH模式就是從訪問地址動手腳,在訪問地址的後面增長#而且帶上須要的參數,這樣後臺就能對不一樣的參數顯示不一樣的模塊,並且 #以及後面的參數是不會被包含在HTTP請求中,所以對服務器的請求是沒有影響的,更改參數也不會刷新頁面。例子:網易雲音樂的官網https://music.163.com/#
    history模式:
    history模式也是從訪問地址動手腳,可是再也不使用#,而是想普通的訪問地址那樣使用/,但若是這樣請求的話,服務器是須要另外配置才行,要否則容易出現404錯誤,具體怎麼配置請自行百度。
複製代碼

內存泄漏

1 意外的全局變量沒法被回收
2 定時器未被正確關閉,致使使用的外部變量沒法被釋放
3 事件監聽未正確被銷燬
4 閉包,會致使父級中變量沒法被釋放
5 dom引用,dom元素被刪除時,內存中的引用未被正確清空
可用chrome中的timeline來進行內存標記~
複製代碼

解決閉包的內存泄露

window.onload = function(){
    var el = document.getElementById("id");
    var id = el.id; //解除循環引用
    el.onclick = function(){
        alert(id); 
    }
    el = null; // 將閉包引用的外部函數中活動對象清除
}
複製代碼

Http1.0 1.1 2.0的區別

資料參考:HTTP1.0、HTTP1.1 和 HTTP2.0 的區別

資料參考:如何優雅的談論HTTP/1.0/1.1/2.0

HTTP1.1是當前使用最爲普遍的HTTP協議

  • HTTP1.0和HTTP1.1相比

    緩存處理:在HTTP1.0中主要使用header裏的If-Modified-Since,Expires來作爲緩存判斷的標準,HTTP1.1則引入了更多的緩存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供選擇的緩存頭來控制緩存策略。

    帶寬優化及網絡鏈接的使用:HTTP1.0中,存在一些浪費帶寬的現象,例如客戶端只是須要某個對象的一部分,而服務器卻將整個對象送過來了,而且不支持斷點續傳功能,HTTP1.1則在請求頭引入了range頭域,它容許只請求資源的某個部分,即返回碼是206(Partial Content),這樣就方便了開發者自由的選擇以便於充分利用帶寬和鏈接。

    錯誤通知的管理:在HTTP1.1中新增了24個錯誤狀態響應碼,如409(Conflict)表示請求的資源與資源的當前狀態發生衝突;410(Gone)表示服務器上的某個資源被永久性的刪除。

    Host頭處理:在HTTP1.0中認爲每臺服務器都綁定一個惟一的IP地址,所以,請求消息中的URL並無傳遞主機名(hostname)。但隨着虛擬主機技術的發展,在一臺物理服務器上能夠存在多個虛擬主機(Multi-homed Web Servers),而且它們共享一個IP地址。HTTP1.1的請求消息和響應消息都應支持Host頭域,且請求消息中若是沒有Host頭域會報告一個錯誤(400 Bad Request)。

    長鏈接:HTTP 1.1支持長鏈接(PersistentConnection)和請求的流水線(Pipelining)處理,在一個TCP鏈接上能夠傳送多個HTTP請求和響應,減小了創建和關閉鏈接的消耗和延遲,在HTTP1.1中默認開啓Connection: keep-alive,必定程度上彌補了HTTP1.0每次請求都要建立鏈接的缺點。 經過設置http的請求頭部和應答頭部,保證本次數據請求結束以後,下一次請求仍能夠重用這一通道,避免從新握手。

  • HTTP2.0和HTTP1.X相比

    新的二進制格式(Binary Format):HTTP1.x的解析是基於文本。基於文本協議的格式解析存在自然缺陷,文本的表現形式有多樣性,要作到健壯性考慮的場景必然不少,二進制則不一樣,只認0和1的組合。基於這種考慮HTTP2.0的協議解析決定採用二進制格式,實現方便且健壯。

    多路複用(MultiPlexing):即鏈接共享,即每個request都是是用做鏈接共享機制的。一個request對應一個id,這樣一個鏈接上能夠有多個request,每一個鏈接的request能夠隨機的混雜在一塊兒,接收方能夠根據request的 id將request再歸屬到各自不一樣的服務端請求裏面。

    header壓縮:如上文中所言,對前面提到過HTTP1.x的header帶有大量信息,並且每次都要重複發送,HTTP2.0使用了專門爲首部壓縮而設計的 HPACK 算法,使用encoder來減小須要傳輸的header大小,通信雙方各自cache一份header fields表,既避免了重複header的傳輸,又減少了須要傳輸的大小。

    服務端推送(server push):服務端推送能把客戶端所須要的資源伴隨着index.html一塊兒發送到客戶端,省去了客戶端重複請求的步驟。正由於沒有發起請求,創建鏈接等操做,因此靜態資源經過服務端推送的方式能夠極大地提高速度。例如個人網頁有一個sytle.css的請求,在客戶端收到sytle.css數據的同時,服務端會將sytle.js的文件推送給客戶端,當客戶端再次嘗試獲取sytle.js時就能夠直接從緩存中獲取到,不用再發請求了。

  • HTTPS與HTTP相比

    HTTPS協議須要到CA申請證書,通常免費證書不多,須要交費。

    HTTP協議運行在TCP之上,全部傳輸的內容都是明文,HTTPS運行在SSL/TLS之上,SSL/TLS運行在TCP之上,全部傳輸的內容都通過加密的。

    HTTP和HTTPS使用的是徹底不一樣的鏈接方式,用的端口也不同,前者是80,後者是443。

    HTTPS能夠有效的防止運營商劫持,解決了防劫持的一個大問題。

  • HTTS

    HTTPS在傳輸數據以前須要客戶端(瀏覽器)與服務端(網站)之間進行一次握手,在握手過程當中將確立雙方加密傳輸數據的密碼信息。TLS/SSL協議不只僅是一套加密傳輸的協議,TLS/SSL中使用了非對稱加密,對稱加密以及HASH算法。

    握手過程的簡單描述以下:

    1.瀏覽器將本身支持的一套加密規則發送給網站。
      2.網站從中選出一組加密算法與HASH算法,並將本身的身份信息以證書的形式發回給瀏覽器。證書裏面包含了網站地址,加密公鑰,以及證書的頒發機構等信息。
      3.得到網站證書以後瀏覽器要作如下工做:
          a) 驗證證書的合法性(頒發證書的機構是否合法,證書中包含的網站地址是否與正在訪問的地址一致等),若是證書受信任,則瀏覽器欄裏面會顯示一個小鎖頭,不然會給出證書不受信的提示。
          b) 若是證書受信任,或者是用戶接受了不受信的證書,瀏覽器會生成一串隨機數的密碼,並用證書中提供的公鑰加密。
          c) 使用約定好的HASH計算握手消息,並使用生成的隨機數對消息進行加密,最後將以前生成的全部信息發送給網站。
      4.網站接收瀏覽器發來的數據以後要作如下的操做:
          a) 使用本身的私鑰將信息解密取出密碼,使用密碼解密瀏覽器發來的握手消息,並驗證HASH是否與瀏覽器發來的一致。
          b) 使用密碼加密一段握手消息,發送給瀏覽器。
      5.瀏覽器解密並計算握手消息的HASH,若是與服務端發來的HASH一致,此時握手過程結束,以後全部的通訊數據將由以前瀏覽器生成的隨機密碼並利用對稱加密算法進行加密。
    複製代碼

    這裏瀏覽器與網站互相發送加密的握手消息並驗證,目的是爲了保證雙方都得到了一致的密碼,而且能夠正常的加密解密數據。其中非對稱加密算法用於在握手過程當中加密生成的密碼,對稱加密算法用於對真正傳輸的數據進行加密,而HASH算法用於驗證數據的完整性。因爲瀏覽器生成的密碼是整個數據加密的關鍵,所以在傳輸的時候使用了非對稱加密算法對其加密。非對稱加密算法會生成公鑰和私鑰,公鑰只能用於加密數據,所以能夠隨意傳輸,而網站的私鑰用於對數據進行解密,因此網站都會很是當心的保管本身的私鑰,防止泄漏。 TLS握手過程當中若是有任何錯誤,都會使加密鏈接斷開,從而阻止了隱私信息的傳輸。正是因爲HTTPS很是的安全,攻擊者沒法從中找到下手的地方,因而更多的是採用了假證書的手法來欺騙客戶端,從而獲取明文的信息。

http請求

  • 請求報文
    • 請求行:請求方法字段、URL字段和HTTP協議版本 例如:GET /index.html HTTP/1.1
    • 請求頭:key value形式,如User-Agent:產生請求的瀏覽器類型; Accept:客戶端可識別的內容類型列表;Host:主機地址
    • 請求數據:post方法中,會把數據以key value形式發送請求
    • 空行:發送回車符和換行符,通知服務器如下再也不有請求頭
  • 響應報文
    • 狀態行:http版本+狀態碼+狀態代碼的文本描述 例如:HTTP/1.1 200 ok
    • 消息報頭:包含服務器類型,日期,長度,內容類型等
    • 響應正文:服務器返回的HTML頁面或者json數據

HTTP緩存機制基原理

資料參考:完全弄懂HTTP緩存機制及原理

web緩存三類:服務器端緩存、瀏覽器端緩存、數據庫數據緩存

  • 強制緩存:在緩存數據未失效的狀況下,能夠直接使用緩存數據。瀏覽器向服務器請求數據時,服務器會將數據和緩存規則一併返回,響應header中會有兩個字段來標明失效規則(Expires/Cache-Control)。

  • 對比緩存:瀏覽器第一次請求數據時,服務器會將緩存標識與數據一塊兒返回給客戶端,客戶端將兩者備份至緩存數據庫中。再次請求數據時,客戶端將備份的緩存標識發送給服務器,服務器根據緩存標識進行判斷,判斷成功後,返回304狀態碼,通知客戶端比較成功,能夠使用緩存數據。

資料參考:HTTP緩存控制小結

優先級從高到低分別是 Pragma -> Cache-Control -> Expires

1.Pragma:禁用緩存。 當該字段值爲no-cache的時候(事實上如今RFC中也僅標明該可選值),會知會客戶端不要對該資源讀緩存,即每次都得向服務器發一次請求才行。

2.Expires: 啓用緩存和定義緩存時間。Expires的值對應一個GMT(格林尼治時間),好比Mon, 22 Jul 2002 11:12:01 GMT來告訴瀏覽器資源緩存過時時間,若是還沒過該時間點則不發請求。

3.Cache-Control:定義緩存過時時間,實現緩存文件是否更新的驗證、提高緩存的複用率

1. Last-Modified

    ⑴ If-Modified-Since: Last-Modified-value
    示例爲 If-Modified-Since: Thu, 31 Mar 2016 07:07:52 GMT
    該請求首部告訴服務器若是客戶端傳來的最後修改時間與服務器上的一致,則直接回送304 和響應報頭便可。
    當前各瀏覽器均是使用的該請求首部來向服務器傳遞保存的 Last-Modified 值。

    ⑵ If-Unmodified-Since: Last-Modified-value
    該值告訴服務器,若Last-Modified沒有匹配上(資源在服務端的最後更新時間改變了),則應當返回412(Precondition Failed) 狀態碼給客戶端。 Last-Modified 存在必定問題,若是在服務器上,一個資源被修改了,但其實際內容根本沒發生改變,會由於Last-Modified時間匹配不上而返回了整個實體給客戶端(即便客戶端緩存裏有個如出一轍的資源)。
    
2. ETag:經過某種算法,給資源計算得出一個惟一標誌符(好比md5標誌),在把資源響應給客戶端的時候,會在實體首部加上「ETag: 惟一標識符」一塊兒返回給客戶端。

    ⑴ If-None-Match: ETag-value
    示例爲 If-None-Match: "5d8c72a5edda8d6a:3239" 告訴服務端若是 ETag 沒匹配上須要重發資源數據,不然直接回送304 和響應報頭便可。 當前各瀏覽器均是使用的該請求首部來向服務器傳遞保存的 ETag 值。

    ⑵ If-Match: ETag-value
    告訴服務器若是沒有匹配到ETag,或者收到了「*」值而當前並無該資源實體,則應當返回412(Precondition Failed) 狀態碼給客戶端。不然服務器直接忽略該字段。
    須要注意的是,若是資源是走分佈式服務器(好比CDN)存儲的狀況,須要這些服務器上計算ETag惟一值的算法保持一致,纔不會致使明明同一個文件,在服務器A和服務器B上生成的ETag卻不同。
複製代碼

服務器再次請求流程

用戶請求匹配規則(nginx相關)

資料參考:Nginx Location指令URI匹配規則詳解

當nginx收到一個請求後,會截取請求的URI部份,去搜索全部location指令中定義的URI匹配模式。在server模塊中能夠定義多個location指令來匹配不一樣的url請求,多個不一樣location配置的URI匹配模式,整體的匹配原則是:先匹配普通字符串模式,再匹配正則模式。

只識別URI部份,例如請求爲:/test/abc/user.do?name=xxxx 
複製代碼
  • Nginx匹配請求的流程:

    1. 先查找是否有=開頭的精確匹配,如:location = /test/abc/user.do { … }

    2. 再查找普通匹配,以 最大前綴 爲原則,若有如下兩個location,則會匹配後一項

      • location /test/ { … }
      • location /test/abc { … }
    3. 匹配到一個普通格式後,搜索並未結束,而是暫存當前匹配的結果,並繼續搜索正則匹配模式

    4. 全部正則匹配模式location中找到第一個匹配項後,就以此項爲最終匹配結果。因此正則匹配項匹配規則,受定義的先後順序影響,但普通匹配模式不會

    5. 若是未找到正則匹配項,則以3中緩存的結果爲最終匹配結果

    6. 若是一個匹配都沒搜索到,則返回404

負載均衡和容錯方式

參考資料:服務器負載均衡的基本功能和實現原理

負責均衡服務器根據負載均衡算法來分發請求到不一樣的主服務器。

每一個主服務器都是等價的,均可以完成相同的功能。

通常來講負載均衡設備都會默認支持多種負載均衡分發策略,例如:

輪詢(RoundRobin)將請求順序循環地發到每一個服務器。當其中某個服務器發生故障,AX就把其從順序循環隊列中拿出,不參加下一次的輪詢,直到其恢復正常。

比率(Ratio):給每一個服務器分配一個加權值爲比例,根椐這個比例,把用戶的請求分配到每一個服務器。當其中某個服務器發生故障,AX就把其從服務器隊列中拿出,不參加下一次的用戶請求的分配,直到其恢復正常。

優先權(Priority):給全部服務器分組,給每一個組定義優先權,將用戶的請求分配給優先級最高的服務器組(在同一組內,採用預先設定的輪詢或比率算法,分配用戶的請求);當最高優先級中全部服務器或者指定數量的服務器出現故障,AX將把請求送給次優先級的服務器組。這種方式,實際爲用戶提供一種熱備份的方式。

最少鏈接數(LeastConnection):AX會記錄當前每臺服務器或者服務端口上的鏈接數,新的鏈接將傳遞給鏈接數最少的服務器。當其中某個服務器發生故障,AX就把其從服務器隊列中拿出,不參加下一次的用戶請求的分配,直到其恢復正常

最快響應時間(Fast Reponse time):新的鏈接傳遞給那些響應最快的服務器。當其中某個服務器發生故障,AX就把其從服務器隊列中拿出,不參加下一次的用戶請求的分配,直到其恢復正常。

哈希算法( hash):  將客戶端的源地址,端口進行哈希運算,根據運算的結果轉發給一臺服務器進行處理,當其中某個服務器發生故障,就把其從服務器隊列中拿出,不參加下一次的用戶請求的分配,直到其恢復正常。

基於策略的負載均衡:針對不一樣的數據流設置導向規則,用戶可自行編輯流量分配策略,利用這些策略對經過的數據流實施導向控制。

基於數據包的內容分發:例如判斷HTTP的URL,若是URL中帶有.jpg的擴展名,就把數據包轉發到指定的服務器。
複製代碼

容錯(fall-over):容錯是負載均衡服務器裏面的一個概念。是指當一臺主服務器宕機後,集羣可以繼續提供服務的策略。好比說當主服務器A宕機後,負載均衡服務器要能發現主服務器A不能繼續提供服務了,之前分發到主服務器A的請求要分發到其它主服務器。這種處理就是容錯處理。

面向對象

參考資料:面向對象(一)|面向對象概念及優勢

面向對象三大特性:封裝、繼承、多態。

面向對象的好處:

  1. 將對象進行分類,分別封裝它們的數據和能夠調用的方法,方便了函數、變量、數據的管理,方便方法的調用(減小重複參數等),尤爲是在編寫大型程序時更有幫助。
  2. 用面向對象的編程能夠把變量當成對象進行操做,讓編程思路更加清晰簡潔,並且減小了不少冗餘變量的出現

方法重寫和重載

方法重寫(overriding):

也叫子類的方法覆蓋父類的方法,要求返回值、方法名和參數都相同。
子類拋出的異常不能超過父類相應方法拋出的異常。(子類異常不能超出父類異常)
子類方法的的訪問級別不能低於父類相應方法的訪問級別(子類訪問級別不能低於父類訪問級別)。
複製代碼

方法重載(overloading):

重載是在同一個類中的兩個或兩個以上的方法,擁有相同的方法名,可是參數卻不相同,方法體也不相同,最多見的重載的例子就是類的構造函數。
複製代碼

java後端如何存取圖片文件

資料參考:java後臺接受到圖片後保存方法

前端代碼:

<form enctype="multipart/form-data" method="post" action="/testUploadimg"> 
    圖片:<input type="file" name="file" /><br/> 
    <input type="submit" value="上傳" />.
</form>
複製代碼

後端代碼:

//調整頁面請求

@Controllerpublic class UploadController {  
//跳轉到上傳文件的頁面  
@RequestMapping(value = "/gouploadimg", method = RequestMethod.GET)  
    public String goUploadImg() {    
    //跳轉到 templates 目錄下的 uploadimg.html    
    return "uploadimg";  
}  
 
//處理文件上傳  
@ResponseBody //返回json數據  
@RequestMapping(value = "/testUploadimg", method = RequestMethod.POST)  
 
//上傳請求方法
public String uploadImg(@RequestParam("file") MultipartFile file, HttpServletRequest request) {    
    tring contentType = file.getContentType();    
    String fileName = file.getOriginalFilename();    
    String filePath = "D:/img";    
    if (file.isEmpty()) {      
        return "文件爲空!";    
    }    
    try {      
        uploadFile(file.getBytes(), filePath, fileName);    
    } catch (Exception e) {      
        // TODO: handle exception    
    }    
    //返回json    
    return "上傳成功";  
}  

//存儲圖片方法
public static void uploadFile(byte[] file, String filePath, String fileName) throws Exception {    
    File targetFile = new File(filePath);    
    if (!targetFile.exists()) {      
        targetFile.mkdirs();    
    }    
    FileOutputStream out = new FileOutputStream(filePath +"/"+ fileName);    
    out.write(file);    
    out.flush();    
    out.close();  
    }
}
複製代碼

如何鑑權

資料參考:先後端常見的幾種鑑權方式

經常使用的鑑權有四種:

  1. HTTP Basic Authentication
  2. session-cookie
  3. Token 驗證
  4. OAuth(開放受權)
  • HTTP Basic Authentication:HTTP服務器對客戶端進行用戶身份證的方法

    1. 客戶端向服務器請求數據,請求的內容多是一個網頁或者是一個ajax異步請求,此時,假設客戶端還沒有被驗證,則客戶端提供以下請求至服務器:Get /index.html HTTP/1.0; Host:www.google.com
    2. 服務器向客戶端發送驗證請求代碼401,(WWW-Authenticate: Basic realm=」google.com」這句話是關鍵,若是沒有客戶端不會彈出用戶名和密碼輸入界面)
    3. 當符合http1.0或1.1規範的客戶端(如IE,FIREFOX)收到401返回值時,將自動彈出一個登陸窗口,要求用戶輸入用戶名和密碼。
    4. 用戶輸入用戶名和密碼後,將用戶名及密碼以BASE64加密方式加密,並將密文放入前一條請求信息中,則客戶端發送的第一條請求信息則變成以下內容:Get /index.html HTTP/1.0; Host:www.google.com;Authorization: Basic d2FuZzp3YW5n → 用戶名:密碼 經過base64加密,是瀏覽器默認的行爲,不須要人爲加密
    5. 服務器收到上述請求信息後,將Authorization字段後的用戶信息取出、解密,將解密後的用戶名及密碼與用戶數據庫進行比較驗證,如用戶名及密碼正確,服務器則根據請求,將所請求資源發送給客戶端

    缺陷:加密方式簡單,是base64加密是可逆的。同時在每一個請求的頭上都會附帶上用戶名和密碼信息,這樣在外網是很容易被嗅探器探測到的。

  • session-cookie:利用服務器端的session(會話)和瀏覽器端的cookie來實現先後端的認證。在服務器端建立一個會話(seesion),將同一個客戶端的請求都維護在各自的會話中,每當請求到達服務器端的時候,先去查一下該客戶端有沒有在服務器端建立seesion,若是有則已經認證成功了,不然就沒有認證。

    1. 服務器在接受客戶端首次訪問時在服務器端建立seesion,而後保存seesion(咱們能夠將seesion保存在內存中,也能夠保存在redis中,推薦使用後者),而後給這個session生成一個惟一的標識字符串,而後在響應頭中種下這個惟一標識字符串。
    2. 簽名。這一步只是對sid進行加密處理,服務端會根據這個secret密鑰進行解密。(非必需步驟)
    3. 瀏覽器中收到請求響應的時候會解析響應頭,而後將sid保存在本地cookie中,瀏覽器在下次http請求的請求頭中會帶上該域名下的cookie信息。
    4. 服務器在接受客戶端請求時會去解析請求頭cookie中的sid,而後根據這個sid去找服務器端保存的該客戶端的session,而後判斷該請求是否合法。
  • Token 驗證:客戶端在首次登錄之後,服務端再次接收http請求的時候,就只認token了,請求只要每次把token帶上就好了,服務器端會攔截全部的請求,而後校驗token的合法性,合法就放行,不合法就返回401(鑑權失敗)

    1. 客戶端使用用戶名跟密碼請求登陸
    2. 服務端收到請求,去驗證用戶名與密碼
    3. 驗證成功後,服務端會簽發一個 Token,再把這個 Token 發送給客戶端
    4. 客戶端收到 Token 之後能夠把它存儲起來,好比放在 Cookie 裏或者 Local Storage 裏
    5. 客戶端每次向服務端請求資源的時候須要帶着服務端簽發的 Token
    6. 服務端收到請求,而後去驗證客戶端請求裏面帶着的Token,若是驗證成功,就向客戶端返回請求的數據
  • OAuth(開放受權):容許用戶受權第三方網站訪問他們存儲在另外的服務提供者上的信息,而不須要將用戶名和密碼提供給第三方網站或分享他們數據的全部內容。爲了保護用戶數據的安全和隱私,第三方網站訪問用戶數據前都須要顯式的向用戶徵求受權。咱們常見的提供OAuth認證服務的廠商有支付寶,QQ,微信。

    1. 向用戶請求受權,如今不少的網站在登錄的時候都有第三方登錄的入口,當咱們點擊等第三方入口時,第三方受權服務會引導咱們進入第三方登錄受權頁面。
    2. 返回用戶憑證(code),並返回一個憑證(code),當用戶點擊受權並登錄後,受權服務器將生成一個用戶憑證(code)。這個用戶憑證會附加在重定向的地址redirect_uri的後面
    3. 第三方應用後臺經過第二步的憑證(code)向受權服務器請求Access Token
    4. 受權服務器贊成受權後,返回一個資源訪問的憑證(Access Token)
    5. 第三方應用經過第四步的憑證(Access Token)向資源服務器請求相關資源
    6. 資源服務器驗證憑證(Access Token)經過後,將第三方應用請求的資源返回

cookie session localStorage sessionStorage

cookie:客戶端保存狀態的一種方案。
    服務器在Http響應的頭中加入一行特殊的指令用以在客戶端生成相應的cookie。
    保存在內存裏,不超過4K
    cookie = new Cookie("username","aaa");
    cookie.setMaxAge(0);
    response.addCookie(cookie);
session:在服務端實現。
    檢查客戶端請求中的sessionID,檢索或建立
    服務端會設置一個響應頭Set-Cookie,返回給客戶端,例如:Set-Cookie:SESSIONID=12345678;客戶端接收到這個響應後,此後發送的每個請求瀏覽器都會自動帶上Cookie請求頭,對應內容是Cookie:SESSIONID=12345678。在服務端內存中存有session,將客戶端發送的請求中的cookie值與內存中的session進行對比,就能夠識別這個客戶端了。
    session有一個缺陷:若是web服務器作了負載均衡,那麼下一個操做請求到了另外一臺服務器的時候session會丟失。
複製代碼

! 重要信息放在session中,其餘保留信息放在cookie中!

session token

token的意思是「令牌」,是用戶身份的驗證方式,最簡單的token組成:uid(用戶惟一的身份標識)、time(當前時間的時間戳)、sign(簽名,由token的前幾位+鹽以哈希算法壓縮成必定長的十六進制字符串,能夠防止惡意第三方拼接token請求服務器)。還能夠把不變的參數也放進token,避免屢次查庫

session 和 oauth token並不矛盾,做爲身份認證token安全性比session好,由於每一個請求都有簽名還能防止監聽以及重放攻擊,而session就必須靠鏈路層來保障通信安全了。

Session 是一種HTTP存儲機制,目的是爲無狀態的HTTP提供的持久機制。所謂Session 認證只是簡單的把User 信息存儲到Session 裏,由於SID 的不可預測性,暫且認爲是安全的。這是一種認證手段。 而Token ,若是指的是OAuth Token 或相似的機制的話,提供的是 認證 和 受權 ,認證是針對用戶,受權是針對App 。其目的是讓 某App有權利訪問 某用戶 的信息。這裏的 Token是惟一的。不能夠轉移到其它 App上,也不能夠轉到其它 用戶 上。 轉過來講Session 。Session只提供一種簡單的認證,即有此 SID,即認爲有此 User的所有權利。是須要嚴格保密的,這個數據應該只保存在站方,不該該共享給其它網站或者第三方App。 因此簡單來講,若是你的用戶數據可能須要和第三方共享,或者容許第三方調用 API 接口,用 Token 。若是永遠只是本身的網站,本身的 App,用什麼就無所謂了。

token就是令牌,好比你受權(登陸)一個程序時,他就是個依據,判斷你是否已經受權該軟件;cookie就是寫在客戶端的一個txt文件,裏面包括你登陸信息之類的,這樣你下次在登陸某個網站,就會自動調用cookie自動登陸用戶名;session和cookie差很少,只是session是寫在服務器端的文件,也須要在客戶端寫入cookie文件,可是文件裏是你的瀏覽器編號.Session的狀態是存儲在服務器端,客戶端只有session id;而Token的狀態是存儲在客戶端。

localStorage設置過時時間

參考資料:localStorage設置過時時間實例

localStorage的數據若是不進行手動刪除或者刪除緩存的話,是永久保存的。

給一個過時的時間,放在第二個參數中。在調用數據的時候,判斷當前時間是否大於設置的過時時間,若是是,就將數據刪除,作一個相應提示或操做便可。

let setTime = new Date().getTime() + (1000 * 60);    // 測試,設置1分鐘後數據過時
 
localStorage.setItem('test', JSON.stringify({
    data: 'data1',
    expiration: setTime
}));
 
 
let data = localStorage.test;
data = JSON.parse(data)
 
let time = data.expiration;
let value = data.data;
 
if(new Date().getTime() > time) {
    delete localStorage.test;
    // 這裏開始執行超時的代碼
}
else {
    // 這裏開始執行未超時的代碼
}
複製代碼

OSI七層網絡模型

資料參考:一張很是強大的OSI七層模型圖解

OSI

TCP/IP

資料參考:關於TCP/IP,必須知道的十個知識點

待補充!!

線程和進程

根本區別:進程是操做系統資源分配的基本單位,而線程是任務調度和執行的基本單位。

在開銷方面:每一個進程都有獨立的代碼和數據空間(程序上下文),程序之間的切換會有較大的開銷;線程能夠看作輕量級的進程,同一類線程共享代碼和數據空間,每一個線程都有本身獨立的運行棧和程序計數器(PC),線程之間切換的開銷小。

所處環境:在操做系統中能同時運行多個進程(程序);而在同一個進程(程序)中有多個線程同時執行(經過CPU調度,在每一個時間片中只有一個線程執行)。

內存分配方面:系統在運行的時候會爲每一個進程分配不一樣的內存空間;而對線程而言,除了CPU外,系統不會爲線程分配內存(線程所使用的資源來自其所屬進程的資源),線程組之間只能共享資源。

包含關係:沒有線程的進程能夠看作是單線程的,若是一個進程內有多個線程,則執行過程不是一條線的,而是多條線(線程)共同完成的;線程是進程的一部分,因此線程也被稱爲輕權進程或者輕量級進程。
複製代碼

瀏覽器三線程:

js引擎線程:是基於事件驅動的單線程
GUI渲染線程:負責渲染瀏覽器界面,與Js互斥
瀏覽器事件觸發線程:把待處理的任務放到任務隊列中,等js主線程空閒再處理
複製代碼

攻擊

XSS攻擊:

着重:注入代碼實現
表現:跨站腳本攻擊,容許用戶將代碼植入,提供給其餘用戶使用的頁面,如html代碼和客戶端腳本。
防範:設置httpOnly,禁止用document.cookie操做;輸入檢查:在用戶輸入的時候進行格式檢查;對輸出轉義。
複製代碼

CSRF攻擊:

着重:攻擊效果
表現:跨站點請求僞造,欺騙用戶的瀏覽器,發送http請求給目標站點。
防禦:1 設置白名單;
      2 限制不被第三方網站請求;
      3 檢查 Referer字段:這個字段用以標明請求來源於哪一個地址。在處理敏感數據請求時,一般來講,Referer 字段應和請求的地址位於同一域名下;
      4 添加校驗 Token:這種數據一般是表單中的一個數據項。服務器生成token並附加在表單中,其內容是一個僞亂數。當客戶端經過表單提交請求時,這個僞亂數也一併提交上去以供校驗。正常的訪問時,客戶端瀏覽器可以正確獲得並傳回這個僞亂數,而經過 CSRF 傳來的欺騙性攻擊中,攻擊者無從事先得知這個僞亂數的值,服務器端就會由於校驗 Token 的值爲空或者錯誤,拒絕這個可疑請求。
      5 經過輸入驗證碼來校驗合法請求。
複製代碼

sql注入攻擊:

攻擊方式:服務器上的數據庫運行非法的 SQL語句,主要經過拼接字符串的形式來完成,改變sql語句自己的語義。經過sql語句實現無帳號登錄,甚至篡改數據庫。
防護:1 使用參數化查詢:使用預編譯語句,預先編譯的SQL語句,而且傳入適當參數屢次執行。因爲沒有拼接的過程,所以能夠防止 SQL注入的發生。使用preparedStatement的參數化sql,經過先肯定語義,再傳入參數,就不會由於傳入的參數改變sql的語義。(經過setInt,setString,setBoolean傳入參數)
      2 單引號轉換:將傳入的參數中的單引號轉換爲連續兩個單引號,PHP 中的 Magic quote 能夠完成這個功能。
      3 檢查變量數據類型和格式。
      4 使用正則表達式過濾傳入的參數,對特殊符號過濾或者轉義處理。
複製代碼

掃描二維碼登入PC的工做原理

1 pc端隨機生成一個含有惟一uid的二維碼,並與服務器創建一個長鏈接;
2 手機掃描二維碼,解析出二維碼中的uid,並把這個uid和手機端的用戶密碼進行綁定,上傳給服務器;
3 服務器得到客戶端信息以後,pc端的長鏈接輪詢操做會得到該消息,顯示該帳號的信息;
4 pc端會再開一個長鏈接與手機端保持通訊,等待手機端確認登錄後,得到服務器受權的token,就能夠在pc端登錄進行正常通訊了。
複製代碼

前端基礎

ajax

概念

向服務器請求額外的數據而無需卸載頁面

HTTP頭部信息:服務器接收頭部信息,決定後續操做。

header:服務器以HTTP協議傳HTML資料到瀏覽器前所送出的字符串。`協議頭字段名:內容`
複製代碼

get和post區別

參考資料:HTTP 方法:GET 對比 POST

  • 簡單區別
比較 GET POST
後退按鈕/刷新 無害 數據會被從新提交(瀏覽器應該告知用戶數據會被從新提交)。
書籤 可收藏爲書籤 不可收藏爲書籤
緩存 能被緩存 不能緩存
編碼類型 application/x-www-form-urlencoded application/x-www-form-urlencoded 或 multipart/form-data。爲二進制數據使用多重編碼。
歷史 參數保留在瀏覽器歷史中。 參數不會保存在瀏覽器歷史中。
對數據長度的限制 是的。當發送數據時,GET 方法向 URL 添加數據;URL 的長度是受限制的(URL 的最大長度是 2048 個字符)。 無限制。
對數據類型的限制 只容許 ASCII 字符。 沒有限制。也容許二進制數據。
安全性 與 POST 相比,GET 的安全性較差,由於所發送的數據是 URL 的一部分。在發送密碼或其餘敏感信息時毫不要使用 GET ! POST 比 GET 更安全,由於參數不會被保存在瀏覽器歷史或 web 服務器日誌中。
可見性 數據在 URL 中對全部人都是可見的。 數據不會顯示在 URL 中。
  • 數據請求過程

    • GET請求(2次交互):用於向服務器查詢某些信息

    瀏覽器請求tcp鏈接(第一次握手) 服務器答應進行tcp鏈接(第二次握手) 瀏覽器確認,併發送get請求頭和數據(第三次握手,這個報文比較小,因此http會在此時進行第一次數據發送) 服務器返回200 ok響應。

    • POST請求(3次交互):用於向服務器發送應該被保存的數據。post消耗的資源更多。傳送的數據相同,get的速度最可能是post的兩倍。

    瀏覽器請求tcp鏈接(第一次握手) 服務器答應進行tcp鏈接(第二次握手) 瀏覽器確認,併發送post請求頭(第三次握手,這個報文比較小,因此http會在此時進行第一次數據發送) 服務器返回100 continue響應 瀏覽器開始發送數據 服務器返回200 ok響應

FormData類型:序列化表單,建立與表格格式相同的數據

超時設定:timeout屬性;調用ontimeout事件處理程序

原生js實現

核心:XMLHttpRequest對象。使用XHR對象取得新數據,再經過DOM將新數據插入頁面中。與數據格式無關。
複製代碼

建立XHR對象:

var xhr = creatXHR();
//檢測狀態
xhr.onreadystatechange = function(){
    if (xhr.readyState == 4){
        if (( xhr.status >=200 && xhr.status <300 ) || xhr.status == 304 ){
            alert(xhr.responseText);
        }else{
            alert("Request was unsuccessful:" + xhr.statusText);
        }
    }
};
//啓動一個請求以備發送
xhr.open("get","example.txt",true);← 是否異步
//發送請求,無數據則必須有null
xhr.send(null);
複製代碼
readyState 狀態
0 未open
1 已open未send
2 已send未迴應
3 已響應部分
4 已所有響應

react實現

axios:

axios.get(this.props.url).then(function(response){
        // 在這兒實現 setState
    }).catch(function(error){
        // 處理請求出錯的狀況
    });
複製代碼

reqwest:

reqwest({
    url: 'path/to/data.jsonp?foo=bar'
  , type: 'jsonp'
  , jsonpCallback: 'foo'
})
  .then(function (resp) {
    qwery('#content').html(resp.content)
  }, function (err, msg) {
    qwery('#errors').html(msg)
  })
  .always(function (resp) {
    qwery('#hide-this').hide()
  })
複製代碼

vue實現

基礎筆記梳理 - Vue

axios({
    method:'post',
    url:'/user',
    data:{
        firstName:'a',
        lastName:'b'
    }
});
複製代碼

跨域

同源政策(爲何AJAX不能跨域請求)

同源政策:不是同協議/同域名/同端口的網頁沒法相互訪問
策略本質:一個域名的Js在未經容許的狀況下,不得讀取另外一個域名的內容。但瀏覽器並不阻止你向另外一個域名發送請求。
複製代碼

CORS

參考資料:跨域CORS原理及調用具體示例 太難了,弄不懂!

使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通。決定請求或相應是否成功。

XDR類型:X Domain Request類型 只支持get和post

建立XDR實例(異步執行):調用open(請求類型,url),再調用send()

使用:只須要向響應頭header中注入Access-Control-Allow-Origin,這樣瀏覽器檢測到header中的Access-Control-Allow-Origin,則就能夠跨域操做了。

實現CORS通訊的關鍵是服務器。只要服務器實現了CORS接口,就能夠跨源通訊。

  • 簡單請求:post get head

    • Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
    • 瀏覽器 在頭信息之中,添加一個Origin字段,說明本次請求來自哪一個源(協議 + 域名 + 端口)
    GET /cors HTTP/1.1
    Origin: http://api.bob.com
    Host: api.alice.com
    Accept-Language: en-US
    Connection: keep-alive
    User-Agent: Mozilla/5.0...
    複製代碼
    • 服務器 若是Origin指定的域名在許可範圍內,服務器返回的響應,會多出幾個頭信息字段。
    Access-Control-Allow-Origin: http://api.bob.com   → 必含,值要麼是請求時Origin字段的值,要麼是一個*,表示接受任意域名的請求。
    Access-Control-Allow-Credentials: true  →可選。值是一個布爾值,表示是否容許發送Cookie。默認狀況下,Cookie不包括在CORS請求之中。設爲true,即表示服務器明確許可,Cookie能夠包含在請求中,一塊兒發給服務器。這個值也只能設爲true,若是服務器不要瀏覽器發送Cookie,刪除該字段便可。
    Access-Control-Expose-Headers: FooBar → 可選。CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。若是想拿到其餘字段,就必須在Access-Control-Expose-Headers裏面指定。上面的例子指定,getResponseHeader('FooBar')能夠返回FooBar字段的值。
    Content-Type: text/html; charset=utf-8
    複製代碼
  • 非簡單請求 PUT DELETE,或者Content-Type:application/json。

    • 在正式通訊以前,增長一次HTTP查詢請求,稱爲"預檢"請求(preflight)。先詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及能夠使用哪些HTTP動詞和頭信息字段。只有獲得確定答覆,瀏覽器纔會發出正式的XMLHttpRequest請求,不然就報錯。
    瀏覽器發送請求:
    var url = 'http://api.alice.com/cors';
    var xhr = new XMLHttpRequest();
    xhr.open('PUT', url, true);
    xhr.setRequestHeader('X-Custom-Header', 'value');
    xhr.send();
    
    先預檢:
    OPTIONS /cors HTTP/1.1
    Origin: http://api.bob.com
    Access-Control-Request-Method: PUT  → 必須,列出瀏覽器的CORS請求會用到哪些HTTP方法,上例是PUT。
    Access-Control-Request-Headers: X-Custom-Header  → 逗號分隔的字符串,指定瀏覽器CORS請求會額外發送的頭信息字段,上例是X-Custom-Header。
    Host: api.alice.com
    Accept-Language: en-US
    Connection: keep-alive
    User-Agent: Mozilla/5.0...
    複製代碼
    • 服務器確認容許跨源請求,作出迴應
    Access-Control-Allow-Methods: GET, POST, PUT
    Access-Control-Allow-Headers: X-Custom-Header → 若是瀏覽器請求包括Access-Control-Request-Headers字段,則Access-Control-Allow-Headers字段是必需的。它也是一個逗號分隔的字符串,代表服務器支持的全部頭信息字段,不限於瀏覽器在"預檢"中請求的字段。
    Access-Control-Allow-Credentials: true → 
    Access-Control-Max-Age: 1728000 → 可選,用來指定本次預檢請求的有效期,單位爲秒
    複製代碼
    • 服務器端代碼
    response.setHeader("Access-Control-Allow-Origin", "*");  
    複製代碼

圖像ping

JSONP

原理:經過script標籤來引入一個js文件,這個js文件載入成功後會執行咱們在url參數中指定的函數,而且把咱們須要的json數據做爲參數傳入。可是jsonp這種方式是須要服務端對應頁面進行相應配合的。
複製代碼

修改document.domain

適用:瀏覽器中不一樣域的框架之間是不能進行js交互的例如:www.example.com/a.html和example.com/b.html這兩個頁面的document.domain都設成相同的域名就能夠了。但要注意的是,document.domain的設置是有限制的,咱們只能把document.domain設置成自身或更高一級的父域,且主域必須相同。

例如:a.b.example.com 中某個文檔的document.domain能夠設成a.b.example.com、b.example.com、example.com中的任意一個,可是不能夠設成c.a.b.example.com,由於這是當前域的子域,也不能夠設成baidu.com,由於主域已經不相同了。

注意:修改document.domain的方法只適用於不一樣子域的框架間的交互。若是你想經過ajax的方法去與不一樣子域的頁面交互,除了使用jsonp的方法外,還能夠用一個隱藏的iframe來作一個代理。原理就是讓這個iframe載入一個與你想要經過ajax獲取數據的目標頁面處在相同的域的頁面,因此這個iframe中的頁面是能夠正常使用ajax去獲取你要的數據的,而後就是經過咱們剛剛講得修改document.domain的方法,讓咱們能經過js徹底控制這個iframe,這樣咱們就可讓iframe去發送ajax請求,而後收到的數據咱們也能夠得到了。
複製代碼

window.name

對象有個name屬性,該屬性有個特徵:即在一個窗口(window)的生命週期內,窗口載入的全部的頁面都是共享一個window.name的,每一個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的全部頁面中的,並不會因新頁面的載入而進行重置。注意:window.name的值只能是字符串的形式,這個字符串的大小最大能容許2M左右甚至更大的一個容量,具體取決於不一樣的瀏覽器,但通常是夠用了。

原理:在a.html頁面中使用一個隱藏的iframe來充當一箇中間人角色,由iframe去獲取data.html的數據,而後a.html再去獲得iframe獲取到的數據。
複製代碼

HTML5中新引入的window.postMessage()方法

原理:window.postMessage(message,targetOrigin)方法是html5新引進的特性,能夠使用它來向其它的window對象發送消息,不管這個window對象是屬於同源或不一樣源,目前IE8+、FireFox、Chrome、Opera等瀏覽器都已經支持window.postMessage方法。參數:第一個參數message爲要發送的消息,類型只能爲字符串;第二個參數targetOrigin用來限定接收消息的那個window對象所在的域,若是不想限定域,能夠使用通配符 * 接收:要接收消息的window對象,但是經過監聽自身的message事件來獲取傳過來的消息,消息內容儲存在該事件對象的data屬性中。適用:一個頁面有幾個框架的那種狀況,由於每個框架都有一個window對象。在討論第二種方法的時候,咱們說過,不一樣域的框架間是能夠獲取到對方的window對象的,並且也能夠使用window.postMessage這個方法
複製代碼

Comet 服務器推送

一種更高級的ajax技術,讓服務器幾乎可以實時地向客戶端推送數據。

實現方式:長輪詢、流

短輪詢:瀏覽器   —請求→  服務器  —響應→  瀏覽器

長輪詢:瀏覽器   —請求→  服務器  —(有數據可發送時)響應→  瀏覽器

HTTP流:瀏覽器   —請求→  服務器(保持連接打開)   —週期性發送數據→  瀏覽器
複製代碼

web sockets

在一個單獨的持久連接上實現雙向通訊。與服務器進行全雙工、雙向通訊的信道。使用自定義的協議而非HTTP,專門爲快速傳輸小數據設計。

通信相關

前端領域的通信

前端和後端、前端和移動端、前端頁面和iframe、瀏覽器各tab之間、web worker線程通訊、路由間通訊、父子組件通訊
複製代碼

通信的要點和目的

要點:發送者和接收者 / 傳輸媒介 / 數據 / 格式協議
目的:同步數據 / 傳遞指令
複製代碼

重定向和轉發

瀏覽器發送請求,服務器發送特定響應,實現重定向。瀏覽器收到響應後,根據狀態碼判斷重定向,並使用指定新URL從新請求。

轉發:服務器端。TBC。。。

狀態碼

狀態碼 含義
1xx 接受,繼續處理
200 成功,並返回數據
201 已建立
202 已接受
203 成功,但未受權
204 成功,但無內容
205 成功,且重置內容
206 成功,部份內容
301 永久移動,需重定向
302 臨時移動,可以使用URI
304 資源未修改,可以使用緩存
305 需使用代理訪問
400 請求語法錯誤
401 須要身份認證
403 拒絕請求
404 資源不存在
500 服務器錯誤

渲染相關

Reflow和Repaint

應儘可能規避!

repaint:重繪。一部分重畫,不影響總體佈局。如顏色改變。
    例如:visibility:hidden
    監控:使用開發者工具能夠監控頁面重繪
    
reflow:迴流。元素幾何尺寸改變,須要從新驗證並計算渲染樹。
    例如:display:none
    致使reflow的操做:
        1. 調整窗口大小
        2. 改變字體(若用rem設置根目錄字體大小,則不迴流)
        3. 增長或移除樣式表
        4. 內容變化 Input
        5. 激活css僞類
        6. 操做class屬性
        7. 基本操做dom
        8. 計算 offsetWidth / offsetHeight 獲取位置
        9. 在html中直接設置style(會下降代碼利用率,影響性能)
    減小reflow的操做:
        1. 動畫效果position:absolute/fixed 使元素脫離文檔流
        2. 避免使用table
        3. 避免多項內聯樣式
        4. 儘量在元素末端改變class
        5. 精簡dom層級
        6. 使用display:none在隱藏期間配置可能致使屢次reflow的樣式,配置完成後再轉爲可見
        7. 屢次元素css屬性操做寫到同一個class裏
        8. 避免在Js循環裏操做dom
        9. 預置css元素的大小
複製代碼

高頻觸發優化方式:

  • 防抖:屢次高頻操做,只在最後一次執行。策略是當事件被觸發時,設定一個週期延遲執行動做,若期間又被觸發,則從新設定週期,直到週期結束,執行動做。
function debounce(fn, delay) {
    var timer

    return function () {
        var that = this
        var args = arguments

        clearTimeout(timer)
            timer = setTimeout(function () {
            fn.apply(that, args)
        }, delay)
    }
}
複製代碼
  • 節流:每隔一段時間後執行一次。固定週期內,只執行一次動做,如有新事件觸發,不執行。週期結束後,又有事件觸發,開始新的週期。
var throttle = function(func,delay){
    var timer = null;
    var startTime = Date.now();

    return function(){
        var curTime = Date.now();
        var remaining = delay-(curTime-startTime);
        var context = this;
        var args = arguments;

        clearTimeout(timer);
        if(remaining<=0){
            func.apply(context,args);
            startTime = Date.now();
        }else{
            timer = setTimeout(func,remaining);
        }
    }
}

複製代碼

SSR服務端渲染

直接在服務端層獲取數據,渲染出完成的html文件,直接返回給用戶瀏覽器。

原理:1. Node服務,讓先後端運行同一套代碼;
      2. Virtual Dom,讓前端代碼脫離瀏覽器運行。
條件:Node中間層 / React或vue框架

客戶端渲染路線:1. 請求一個html -> 
                2. 服務端返回一個html -> 
                3. 瀏覽器下載html裏面的js/css文件 -> 
                4. 等待js文件下載完成 -> 
                5. 等待js加載並初始化完成 -> 
                6. js代碼終於能夠運行,由js代碼向後端請求數據( ajax/fetch ) -> 
                7. 等待後端數據返回 -> 
                8. 客戶端從無到完整地,把數據渲染爲響應頁面

服務端渲染路線:1. 請求一個html -> 
                2. 服務端請求數據( 內網請求快 ) -> 
                3. 服務器初始渲染(服務端性能好,較快) -> 
                4. 服務端返回已經有正確內容的頁面 -> 
                5. 客戶端請求js/css文件 -> 
                6. 等待js文件下載完成 -> 
                7. 等待js加載並初始化完成 -> 
                8. 客戶端把剩下一部分渲染完成( 內容小,渲染快 )
複製代碼

圖片懶加載

參考資料:圖片懶加載原理及實現

場景:一個頁面中不少圖片,可是首屏只出現幾張,這時若是一次性把圖片都加載出來會影響性能。這時能夠使用懶加載,頁面滾動到可視區在加載。優化首屏加載。
實現:img標籤src屬性爲空或同一空白圖片,給一個data-xx屬性,裏面存放圖片真實地址,當頁面滾動直至此圖片出如今可視區域時,用js取到該圖片的data-xx的值賦給src。
優勢:頁面加載速度快,減輕服務器壓力、節約流量,用戶體驗好。
複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.bootcss.com/jquery/2.1.0/jquery.min.js"></script>
    <style>
        .container{
            max-width: 800px;
            margin:0 auto;
        }
        .container:after{
            content:"";
            display: block;
            clear:both;
        }
        .container img{
            width:50%;
            height:260px;
            float:left;
        }
    </style>
</head>
<body>
    <div class="container">
        <img src="http://s4.sinaimg.cn/mw690/006uWPTUgy72CNFYNjB93&690" alt="1" data-src="http://img4.imgtn.bdimg.com/it/u=951914923,777131061&fm=26&gp=0.jpg">
        <img src="http://s4.sinaimg.cn/mw690/006uWPTUgy72CNFYNjB93&690" alt="1" data-src="http://img1.imgtn.bdimg.com/it/u=637435809,3242058940&fm=26&gp=0.jpg">
        <img src="http://s4.sinaimg.cn/mw690/006uWPTUgy72CNFYNjB93&690" alt="1" data-src="http://img1.imgtn.bdimg.com/it/u=3990342075,2367006974&fm=200&gp=0.jpg">
    </div>

        <script>

            // 一開始沒有滾動的時候,出如今視窗中的圖片也會加載
            start();

            // 當頁面開始滾動的時候,遍歷圖片,若是圖片出如今視窗中,就加載圖片
            var clock; //函數節流
            $(window).on('scroll',function(){
                if(clock){
                    clearTimeout(clock);
                }
                clock = setTimeout(function(){
                    start()
                },200)
            })
            
            function start(){
                 $('.container img').not('[data-isLoading]').each(function () {
                    if (isShow($(this))) {
                        loadImg($(this));
                    }
                })
            }

            // 判斷圖片是否出如今視窗的函數
            function isShow($node){
                return $node.offset().top <= $(window).height()+$(window).scrollTop();
            }

            // 加載圖片的函數,就是把自定義屬性data-src 存儲的真正的圖片地址,賦值給src
            function loadImg($img){
                    $img.attr('src', $img.attr('data-src'));

                    // 已經加載的圖片,我給它設置一個屬性,值爲1,做爲標識
                    // 弄這個的初衷是由於,每次滾動的時候,全部的圖片都會遍歷一遍,這樣有點浪費,因此作個標識,滾動的時候只遍歷哪些尚未加載的圖片
                    $img.attr('data-isLoading',1);
            }
        </script>
</body>
</html>
複製代碼

頁面渲染步驟

1. 解析HTML,生成DOM樹。
    接收HTML文檔,遍歷文檔節點,生成DOM樹。
    可能被CSS和JS加載阻塞!
2. 解析CSS,生成CSSOM規則樹。
    每一個CSS文件分析成StyleSheet對象,包含CSS規則
3. 將DOM樹與CSSOM規則樹合併在一塊兒,生成渲染樹。
    渲染樹:用於顯示,不可見元素則不在樹中。display:none 不在;visibility:hidden 在。
    先從DOM樹根節點開始遍歷可見節點,找到適配的CSS。
4. 遍歷渲染樹開始佈局。計算每一個節點的位置大小信息。
    從渲染樹跟節點開始遍歷,肯定節點對象的大小和位置,輸出盒子模型。
5. 將渲染樹每一個節點繪製到屏幕
    由UI後端組件完成,調用paint()顯示內容。
    
渲染阻塞:script標記將使DOM構建暫停。
    若是腳本中操做了CSSOM,則操做順序 CSSOM => 腳本 => DOM
    CSS引入優先,JS底部置後。
複製代碼

js和css阻塞

1. 外部樣式會阻塞以後的<script>,但<script>會在<link>以後執行
2. 外部css加載時,外部Js也會加載,只是Js執行必須是css執行以後
3. 使用async屬性後,Js異步加載,且沒必要等待css以後執行,也不阻塞後面的Js
4. <script>動態建立時,會在css加載以後加載
複製代碼

async和defer

參考資料:淺談script標籤中的async和defer

普通script:若是遇到script腳本,就會中止頁面的解析進行下載

script
defer:在後臺進行下載,可是並不會阻止文檔的渲染,當頁面解析&渲染完畢後, 會等到全部的defer腳本加載完畢並按照順序執行,執行完畢後會觸發DOMContentLoaded事件。
defer
async:async腳本會在加載完畢後執行。async腳本的加載不計入DOMContentLoaded事件統計
async1
async2

其餘前端常考知識

路由的Js實現

參考資料:原生 js 實現一個前端路由 router

  1. 實現原理:如今前端的路由實現通常有兩種,一種是 Hash 路由,另一種是 History 路由。
  • 2.1. History 路由

    History 接口容許操做瀏覽器的曾經在標籤頁或者框架裏訪問的會話歷史記錄。

    屬性

    History.length 是一個只讀屬性,返回當前 session 中的 history 個數,包含當前頁面在內。舉個例子,對於新開一個 tab 加載的頁面當前屬性返回值 1 。

    History.state 返回一個表示歷史堆棧頂部的狀態的值。這是一種能夠沒必要等待 popstate 事件而查看狀態而的方式。 方法 History.back()前往上一頁, 用戶可點擊瀏覽器左上角的返回按鈕模擬此方法. 等價於 history.go(-1).

    Note: 當瀏覽器會話歷史記錄處於第一頁時調用此方法沒有效果,並且也不會報錯。

    History.forward()在瀏覽器歷史記錄裏前往下一頁,用戶可點擊瀏覽器左上角的前進按鈕模擬此方法. 等價於 history.go(1).

    Note: 當瀏覽器歷史棧處於最頂端時( 當前頁面處於最後一頁時 )調用此方法沒有效果也不報錯。

    History.go(n)經過當前頁面的相對位置從瀏覽器歷史記錄( 會話記錄 )加載頁面。好比:參數爲 -1的時候爲上一頁,參數爲 1 的時候爲下一頁. 當整數參數超出界限時 ( 譯者注:原文爲 When integerDelta is out of bounds ),例如: 若是當前頁爲第一頁,前面已經沒有頁面了,我傳參的值爲 -1,那麼這個方法沒有任何效果也不會報錯。調用沒有參數的 go() 方法或者不是整數的參數時也沒有效果。( 這點與支持字符串做爲 url 參數的 IE 有點不一樣)。

    history.pushState() 和 history.replaceState()這兩個 API 都接收三個參數,分別是

    a. 狀態對象(state object) — 一個JavaScript對象,與用 pushState() 方法建立的新歷史記錄條目關聯。不管什麼時候用戶導航到新建立的狀態,popstate 事件都會被觸發,而且事件對象的state 屬性都包含歷史記錄條目的狀態對象的拷貝。
    
      b. 標題(title) — FireFox 瀏覽器目前會忽略該參數,雖然之後可能會用上。考慮到將來可能會對該方法進行修改,傳一個空字符串會比較安全。或者,你也能夠傳入一個簡短的標題,標明將要進入的狀態。
    
      c. 地址(URL) — 新的歷史記錄條目的地址。瀏覽器不會在調用 pushState() 方法後加載該地址,但以後,可能會試圖加載,例如用戶重啓瀏覽器。新的 URL 不必定是絕對路徑;若是是相對路徑,它將以當前 URL 爲基準;傳入的 URL 與當前 URL 應該是同源的,不然,pushState() 會拋出異常。該參數是可選的;不指定的話則爲文檔當前 URL。
    
      相同之處: 是兩個 API 都會操做瀏覽器的歷史記錄,而不會引發頁面的刷新。
    
      不一樣之處: pushState 會增長一條新的歷史記錄,而 replaceState 則會替換當前的歷史記錄。
    複製代碼

    例子:

    原本的路由http://biaochenxuying.cn/

    執行:window.history.pushState(null, null, "http://biaochenxuying.cn/home");

    路由變成了:http://biaochenxuying.cn/home

  • 2.2 Hash 路由

    咱們常常在 url 中看到 #,這個 # 有兩種狀況,一個是咱們所謂的錨點,好比典型的回到頂部按鈕原理、Github 上各個標題之間的跳轉等,可是路由裏的 # 不叫錨點,咱們稱之爲 hash。

    當 hash 值發生改變的時候,咱們能夠經過 hashchange事件監聽到,從而在回調函數裏面觸發某些方法。

<meta>標籤:

提供有關頁面的源信息,如針對搜索引擎和更新頻率的描述和關鍵詞。

必選:content → 名稱/值對中的值, 能夠是任何有效的字符串。 始終要和 name 屬性或 http-equiv 屬性一塊兒使用。
可選:http-equiv → 沒有name時,會採用這個屬性的值。經常使用的有content-type、expires、refresh、set-cookie。把content屬性關聯到http頭部。
      name → 名稱/值對中的名稱。經常使用的有author、description、keywords、generator、revised、others。 把 content 屬性關聯到一個名稱。
      scheme → 用於指定要用來翻譯屬性值的方案。
<meta http-equiv="charset" content="iso-8859-1">
複製代碼

Babel轉碼器:將ES6轉爲ES5。

1 將ES6/ES7解析爲抽象語法樹
2 對抽象語法樹進行遍歷編譯,獲得新的抽象語法樹
3 將新的抽象語法樹轉換成ES5

抽象語法樹AST:將代碼逐字母解析成樹狀對象。
複製代碼

webpack打包過程:

前端資源加載/打包工具。
把項目看成一個總體,經過一個給定的主文件index.js,從這個文件開始找到項目的全部依賴文件,使用Loader處理,最後打包爲瀏覽器可識別的js文件。

1 讀取文件,分析模塊依賴
2 對模塊進行解析執行(深度遍歷)
3 針對不一樣模塊,使用不一樣的Loader
4 編譯模塊,生成抽象語法樹AST
5 遍歷AST,輸出js
複製代碼

webpack配置文件

  • Loaders

    • 經過使用不一樣的loader,webpack有能力調用外部的腳本或工具,實現對不一樣格式的文件的處理

    • 好比說分析轉換scss爲css,或者把下一代的JS文件(ES6,ES7)轉換爲現代瀏覽器兼容的JS文件,對React的開發而言,合適的Loaders能夠把React的中用到的JSX文件轉換爲JS文件。

    • Loaders須要單獨安裝而且須要在webpack.config.js中的modules關鍵字下進行配置,Loaders的配置包括如下幾方面:

      1. test:一個用以匹配loaders所處理文件的拓展名的正則表達式(必須)
      2. loader:loader的名稱(必須)
      3. include/exclude: 手動添加必須處理的文件(文件夾)或屏蔽不須要處理的文件(文件夾)(可選);
      4. query:爲loaders提供額外的設置選項(可選)
  • babel

    • babel是一種javascript編譯器,它能把最新版的javascript編譯成當下能夠執行的版本,簡言之,利用babel就可讓咱們在當前的項目中隨意的使用這些新最新的es6,甚至es7的語法。說白了就是把各類javascript千奇百怪的語言通通專爲瀏覽器能夠認識的語言。
    • babel的配置選項放在一個單獨的名爲 ".babelrc" 的配置文件中
  • plugins

    • 插件(Plugins)是用來拓展Webpack功能的,它們會在整個構建過程當中生效,執行相關的任務。
  • Loaders和Plugins經常被弄混,可是他們實際上是徹底不一樣的東西,能夠這麼來講:

    • loaders是在打包構建過程當中用來處理源文件的(JSX,Scss,Less..),一次處理一個。
    • 插件並不直接操做單個文件,它直接對整個構建過程其做用。

webpack常見的Plugin?他們是解決什麼問題的?

(1)uglifyjs-webpack-plugin:經過UglifyJS去壓縮js代碼;

(2)commons-chunk-plugin:提取公共代碼;

(3)define-plugin:定義環境變量。

webpack的熱更新是如何作到的?說明其原理?

webpack的熱更新又稱熱替換(Hot Module Replacement),縮寫爲HMR。 這個機制能夠作到不用刷新瀏覽器而將新變動的模塊替換掉舊的模塊。

原理:

(1)第一步,在 webpack 的 watch 模式下,文件系統中某一個文件發生修改,webpack 監聽到文件變化,根據配置文件對模塊從新編譯打包,並將打包後的代碼經過簡單的 JavaScript 對象保存在內存中。

(2)第二步是 webpack-dev-server 和 webpack 之間的接口交互,而在這一步,主要是 dev-server 的中間件 webpack-dev-middleware 和 webpack 之間的交互,webpack-dev-middleware 調用 webpack 暴露的 API對代碼變化進行監控,而且告訴 webpack,將代碼打包到內存中。

(3)第三步是 webpack-dev-server對文件變化的一個監控,這一步不一樣於第一步,並非監控代碼變化從新打包。當咱們在配置文件中配置了devServer.watchContentBase 爲 true 的時候,Server 會監聽這些配置文件夾中靜態文件的變化,變化後會通知瀏覽器端對應用進行 live reload。注意,這兒是瀏覽器刷新,和 HMR 是兩個概念。

(4)第四步也是 webpack-dev-server 代碼的工做,該步驟主要是經過 sockjs(webpack-dev-server 的依賴)在瀏覽器端和服務端之間創建一個 websocket 長鏈接,將 webpack 編譯打包的各個階段的狀態信息告知瀏覽器端,同時也包括第三步中 Server 監聽靜態文件變化的信息。瀏覽器端根據這些 socket 消息進行不一樣的操做。固然服務端傳遞的最主要信息仍是新模塊的 hash 值,後面的步驟根據這一 hash 值來進行模塊熱替換。

(5)webpack-dev-server/client 端並不可以請求更新的代碼,也不會執行熱更模塊操做,而把這些工做又交回給了 webpack,webpack/hot/dev-server 的工做就是根據 webpack-dev-server/client 傳給它的信息以及 dev-server 的配置決定是刷新瀏覽器呢仍是進行模塊熱更新。固然若是僅僅是刷新瀏覽器,也就沒有後面那些步驟了。

(6)HotModuleReplacement.runtime 是客戶端 HMR 的中樞,它接收到上一步傳遞給他的新模塊的 hash 值,它經過 JsonpMainTemplate.runtime 向 server 端發送 Ajax 請求,服務端返回一個 json,該 json 包含了全部要更新的模塊的 hash 值,獲取到更新列表後,該模塊再次經過 jsonp 請求,獲取到最新的模塊代碼。這就是上圖中 七、八、9 步驟。

(7)而第 10 步是決定 HMR 成功與否的關鍵步驟,在該步驟中,HotModulePlugin 將會對新舊模塊進行對比,決定是否更新模塊,在決定更新模塊後,檢查模塊之間的依賴關係,更新模塊的同時更新模塊間的依賴引用。

(8)最後一步,當 HMR 失敗後,回退到 live reload 操做,也就是進行瀏覽器刷新來獲取最新打包代碼。

如何利用webpack來優化前端性能?(提升性能和體驗)

用webpack優化前端性能是指優化webpack的輸出結果,讓打包的最終結果在瀏覽器運行快速高效。

(1)壓縮代碼。刪除多餘的代碼、註釋、簡化代碼的寫法等等方式。能夠利用webpack的UglifyJsPlugin和ParallelUglifyPlugin來壓縮JS文件, 利用cssnano(css-loader?minimize)來壓縮css。使用webpack4,打包項目使用production模式,會自動開啓代碼壓縮。

(2)利用CDN加速。在構建過程當中,將引用的靜態資源路徑修改成CDN上對應的路徑。能夠利用webpack對於output參數和各loader的publicPath參數來修改資源路徑

(3)刪除死代碼(Tree Shaking)。將代碼中永遠不會走到的片斷刪除掉。能夠經過在啓動webpack時追加參數--optimize-minimize來實現或者使用es6模塊開啓刪除死代碼。

(4)優化圖片,對於小圖能夠使用 base64 的方式寫入文件中

(5)按照路由拆分代碼,實現按需加載,提取公共代碼。

(6)給打包出來的文件名添加哈希,實現瀏覽器緩存文件

如何提升webpack的構建速度?

(1)多入口的狀況下,使用commonsChunkPlugin來提取公共代碼;

(2)經過externals配置來提取經常使用庫;

(3)使用happypack實現多線程加速編譯;

(4)使用webpack-uglify-parallel來提高uglifyPlugin的壓縮速度。原理上webpack-uglify-parallel採用多核並行壓縮來提高壓縮速度;

(5)使用tree-shaking和scope hoisting來剔除多餘代碼。

十一、怎麼配置單頁應用?怎麼配置多頁應用?

單頁應用能夠理解爲webpack的標準模式,直接在entry中指定單頁應用的入口便可。

多頁應用的話,能夠使用webpack的 AutoWebPlugin來完成簡單自動化的構建,可是前提是項目的目錄結構必須遵照他預設的規範。

npm打包時須要注意哪些?如何利用webpack來更好的構建?

NPM模塊須要注意如下問題:

(1)要支持CommonJS模塊化規範,因此要求打包後的最後結果也遵照該規則

(2)Npm模塊使用者的環境是不肯定的,頗有可能並不支持ES6,因此打包的最後結果應該是採用ES5編寫的。而且若是ES5是通過轉換的,請最好連同SourceMap一同上傳。

(3)Npm包大小應該是儘可能小(有些倉庫會限制包大小)

(4)發佈的模塊不能將依賴的模塊也一同打包,應該讓用戶選擇性的去自行安裝。這樣能夠避免模塊應用者再次打包時出現底層模塊被重複打包的狀況。

(5)UI組件類的模塊應該將依賴的其它資源文件,例如.css文件也須要包含在發佈的模塊裏。

基於以上須要注意的問題,咱們能夠對於webpack配置作如下擴展和優化:

(1)CommonJS模塊化規範的解決方案: 設置output.libraryTarget='commonjs2'使輸出的代碼符合CommonJS2 模塊化規範,以供給其它模塊導入使用;

(2)輸出ES5代碼的解決方案:使用babel-loader把 ES6 代碼轉換成 ES5 的代碼。再經過開啓devtool: 'source-map'輸出SourceMap以發佈調試。

(3)Npm包大小盡可能小的解決方案:Babel 在把 ES6 代碼轉換成 ES5 代碼時會注入一些輔助函數,最終致使每一個輸出的文件中都包含這段輔助函數的代碼,形成了代碼的冗餘。解決方法是修改.babelrc文件,爲其加入transform-runtime插件

(4)不能將依賴模塊打包到NPM模塊中的解決方案:使用externals配置項來告訴webpack哪些模塊不須要打包。

(5)對於依賴的資源文件打包的解決方案:經過css-loader和extract-text-webpack-plugin來實現,配置以下:

如何在vue項目中實現按需加載?

常常會引入現成的UI組件庫如ElementUI、iView等,可是他們的體積和他們所提供的功能同樣,是很龐大的。 不過不少組件庫已經提供了現成的解決方案,如Element出品的babel-plugin-component和AntDesign出品的babel-plugin-import安裝以上插件後,在.babelrc配置中或babel-loader的參數中進行設置,便可實現組件按需加載了。

webpack開發配置API代理解決跨域問題

使用的是http-proxy-middleware來實現跨域代理

module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': {  → 捕獲API的標誌,開始匹配代理,好比API請求/api/users, 會被代理到請求 http://www.baidu.com/api/users 。
        target: 'http://www.baidu.com/', → 代理的API地址,就是須要跨域的API地址。地址能夠是域名,也能夠是IP地址,若是是域名須要額外添加一個參數changeOrigin: true
        pathRewrite: {'^/api' : ''}, → 路徑重寫,也就是說會修改最終請求的API路徑。目的是給代理命名後,在訪問時把命名刪除掉。
        changeOrigin: true,     // 讓target參數是域名
        secure: false,          // 不檢查安全問題。設置後,能夠接受運行在 HTTPS 上,能夠使用無效證書的後端服務器
      },
      '/api2': {
          .....
      }
    }
  }
};
複製代碼

package.json 常見字段

{
  // 名稱
  "name": "vue",
  // 版本
  "version": "2.6.10",
  // 描述
  "description": "Reactive, component-oriented view layer for modern web interfaces.",
  // npm包項目的主要入口文件,必須的
  "main": "dist/vue.runtime.common.js",
  // rollup 打包須要的入口文件
  "module": "dist/vue.runtime.esm.js",
  // npm 上全部的文件都開啓 cdn 服務地址
  "unpkg": "dist/vue.js",
  // jsdelivr cdn公共庫
  "jsdelivr": "dist/vue.js",
  // TypeScript 的入口文件
  "typings": "types/index.d.ts",
  // 當你發佈package時,具體那些文件會發布上去
  "files": [
    "src",
    "dist/*.js",
    "types/*.d.ts"
  ],
  // 聲明該模塊是否包含 sideEffects(反作用),從而能夠爲 tree-shaking 提供更大的優化空間。
  "sideEffects": false,
  "scripts": {
    "dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev",
    "build": "node scripts/build.js",
    "test": "npm run lint && flow check && npm run test:types && npm run test:cover && npm run test:e2e -- --env phantomjs && npm run test:ssr && npm run test:weex",
    "commit": "git-cz"
    ......
  },
  // 代碼質量檢查
  "gitHooks": {
    "pre-commit": "lint-staged",
    "commit-msg": "node scripts/verify-commit-msg.js"
  },
  // 代碼檢查
  "lint-staged": {
    "*.js": [
      "eslint --fix",
      "git add"
    ]
  },
  // git倉庫所在位置
  "repository": {
    "type": "git",
    "url": "git+https://github.com/vuejs/vue.git"
  },
  // 關鍵詞
  "keywords": [
    "vue"
  ],
  // 做者
  "author": "Evan You",
  // 開源協議
  "license": "MIT",
  // bug地址
  "bugs": {
    "url": "https://github.com/vuejs/vue/issues"
  },
  // 主頁
  "homepage": "https://github.com/vuejs/vue#readme",
  // 依賴
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/plugin-proposal-class-properties": "^7.1.0",
    "acorn": "^5.2.1",
    "babel-eslint": "^10.0.1",
    "eslint": "^5.7.0",
    ......
  },
  // 設置一些用於npm包的腳本命令會用到的配置參數
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }
  // 本node包依賴的其餘依賴包
    "peerDependencies": {
        "vue": "^2.5.2"
    },
    // 指明瞭該項目所須要的node.js版本
    "engines": {
        "node": ">=8.9.1",
        "npm": ">=5.5.1",
        "yarn": ">=1.3.2"
    },
    // 支持的瀏覽器
    "browserslist": [
        "last 3 Chrome versions",
        "last 3 Firefox versions",
        "Safari >= 10",
        "Explorer >= 11",
        "Edge >= 12",
        "iOS >= 10",
        "Android >= 6"
    ]
}
複製代碼

web兼容性問題

參考資料:web前端兼容性問題總結

MVC和MVVM

參考資料:淺析前端開發中的 MVC/MVP/MVVM 模式

  • Model層:用於封裝和應用程序的業務邏輯相關的數據 [和對應處理數據的方法]。
  • View層:做爲視圖層,主要負責數據的展現。
  • controller層:定義用戶界面對用戶輸入的響應方式,鏈接模型和視圖,用於控制應用程序的流程,處理用戶的行爲和數據上的改變。

MVC:容許在不改變視圖的狀況下改變視圖對用戶輸入的響應方式,用戶對View的操做交給了Controller處理,在Controller中響應View的事件調用Model的接口對數據進行操做,一旦Model發生變化便通知相關視圖進行更新。

MVP:是MVC模式的改良。Controller/Presenter負責業務邏輯,Model管理數據,View負責顯示。 MVP中的View並不能直接使用Model,而是經過爲Presenter提供接口,讓Presenter去更新Model,再經過觀察者模式更新View。 解耦View和Model,徹底分離視圖和模型使職責劃分更加清晰;因爲View不依賴Model,能夠將View抽離出來作成組件,它只須要提供一系列接口提供給上層操做。

MVVM:把View和Model的同步邏輯自動化了。View和Model同步再也不手動地進行操做,而是交給框架所提供的數據綁定功能進行負責,只須要告訴它View顯示的數據對應的是Model哪一部分便可。View經過使用模板語法來聲明式的將數據渲染進DOM,當ViewModel對Model進行更新的時候,會經過數據綁定更新到View。

設計模式

參考資料:JavaScript設計模式 單例模式

定義:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
實現方法:先判斷實例存在與否,若是存在則直接返回,若是不存在就建立了再返回,這就確保了一個類只有一個實例對象。
適用場景:一個單一對象。好比:彈窗,不管點擊多少次,彈窗只應該被建立一次。
複製代碼

發佈/訂閱模式

定義:又叫觀察者模式,它定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都將獲得通知。
場景:訂閱感興趣的專欄和公衆號。
複製代碼

策略模式

定義:將一個個算法(解決方案)封裝在一個個策略類中。
優勢:策略模式能夠避免代碼中的多重判斷條件。
      策略模式很好的體現了開放-封閉原則,將一個個算法(解決方案)封裝在一個個策略類中。便於切換,理解,擴展。
      策略中的各類算法能夠重複利用在系統的各個地方,避免複製粘貼。
      策略模式在程序中或多或少的增長了策略類。但比堆砌在業務邏輯中要清晰明瞭。
      違反最少知識原則,必需要了解各類策略類,才能更好的在業務中應用。
應用場景:根據不一樣的員工績效計算不一樣的獎金;表單驗證中的多種校驗規則。
複製代碼

單頁面應用

在一個頁面上集成多種功能,全部業務功能都是子版塊,經過特定的方式掛接到主界面上。
採用MV*框架,在JS層建立模塊分層和通訊機制。
代碼隔離:
    子功能代碼隔離
    頁面模板隔離
樣式規劃:
    基準樣式分離(瀏覽器樣式、全局樣式、佈局、響應支持
    組件樣式劃分(界面組件及子元素樣式、修飾樣式)
    堆疊次序管理(提早爲UI組件規劃次序)
先後端自然分離,以API爲分界
缺陷:不利於搜索引擎優化
把產品功能劃分爲若干狀態,每一個狀態映射到相應的路由
在非首次請求中,使用緩存或本地存儲
採用websocket實時通信。前端只響應確實產生業務數據的事件。
複製代碼

單頁面應用的優劣

  • 優勢:

    • 分離先後端關注點,前端負責界面顯示,後端負責數據存儲和計算,各司其職,不會把先後端的邏輯混雜在一塊兒;
    • 易於代碼複用,同一套後端程序代碼,不用修改就能夠用於Web界面、手機、平板等多種客戶端;
    • 頁面切換速度快。視覺上頁面的切換,只是技術上同一頁面兩個區塊之間的切換
  • 缺點:

    • SEO問題,如今能夠經過Prerender等技術解決一部分;
    • 前進、後退、地址欄等,須要程序進行管理;
    • 書籤,須要程序來提供支持;
    • 請求資源大小增長,打開頁面速度變慢,能夠經過拆分加載解決

web性能優化

資料參考:嗨,送你一張Web性能優化地圖

性能優化

  • 度量標準

    1. 首次有效繪製(First Meaningful Paint,簡稱FMP,當主要內容呈如今頁面上)
    2. 英雄渲染時間(Hero Rendering Times,度量用戶體驗的新指標,當用戶最關心的內容渲染完成)
    3. 可交互時間(Time to Interactive,簡稱TTI,指頁面佈局已經穩定,關鍵的頁面字體是可見的,而且主進程可用於處理用戶輸入,基本上用戶能夠點擊UI並與其交互)
    4. 輸入響應(Input responsiveness,界面響應用戶輸入所需的時間)
    5. 感知速度指數(Perceptual Speed Index,簡稱PSI,測量頁面在加載過程當中視覺上的變化速度,分數越低越好)
    6. 自定義指標,由業務需求和用戶體驗來決定。
  • 編碼優化

    1. 數據讀取速度:對象嵌套的越深,讀取速度就越慢;對象在原型鏈中存在的位置越深,找到它的速度就越慢
    2. DOM:儘量減小訪問DOM的次數;減小重排與重繪的次數;善於使用事件委託
    3. 流程控制:減小迭代的次數;基於循環的迭代比基於函數的迭代快8倍;在JS中倒序循環會略微提高性能
  • 靜態資源優化

    1. 使用Brotli或Zopfli進行純文本壓縮
    2. 圖片優化:儘量經過srcset,sizes和元素使用響應式圖片。
  • 交付優化:對頁面加載資源以及用戶與網頁之間的交付過程進行優化

    1. 異步無阻塞加載JS:將Script標籤放到頁面的最底部;使用defer或async
    2. 使用Intersection Observer實現懶加載:延遲加載圖片、視頻、廣告腳本、或任何其餘資源
    3. 優先加載關鍵的CSS:將首屏渲染必須用到的CSS提取出來內嵌到中,而後再將剩餘部分的CSS用異步的方式加載
    4. 資源提示:Resource Hints
    5. Preload:經過一個現有元素(例如:img,script,link)聲明資源會將獲取與執行耦合在一塊兒
    6. 快速響應的用戶界面:使用骨架屏或添加一些Loading過渡動畫提示用戶體驗
  • 構建優化:影響構建後文件的體積、代碼執行效率、文件加載時間、首次有效繪製指標

    1. 使用預編譯
    2. 使用 Tree-shaking、Scope hoisting、Code-splitting
    3. 服務端渲染(SSR):使用服務端渲染靜態HTML來得到更快的首次有效繪製,一旦JavaScript加載完畢再將頁面接管下來
    4. 使用import函數動態導入模塊,按需加載
    5. 使用HTTP緩存頭:推薦使用Cache-control: immutable避免從新驗證

靜態資源優化

資料參考:Web前端性能優化——如何有效提高靜態文件的加載速度

  1. 代碼壓縮 使用webpack
  2. 文件合併 合併js腳本文件 合併css樣式文件
  3. 在webpack的配置中增長gzip壓縮配置
  4. CDN和緩存

App端網頁和PC端網頁設計起來有什麼區別?

1. 手機網頁主要webkit,PC網頁主要ie。且手機端須要跨系統平臺
2. app端,須要基於phoneGap調用手機核心功能接口(地理定位、聯繫人、加速器、聲音、振動)。模擬tive app,編譯成各系統平臺的app
3. 設置高度、寬度是否能縮放。
    <meta name="viewPort" content="width=device-width,inital-scale=1.0, minimun-scale=0.5,maximum=scale=1.0,user-scalable=no"
4. 自適應,對不一樣像素的屏幕寫不一樣的樣式
    @media only screen and (min-device-width:320px) and (max-device-width:480){...}
5. 用戶體驗不一樣(鼠標與觸屏)
複製代碼

計算在一個頁面上的停留時間

方案1:websocket,前端開個長鏈接,後臺統計長鏈接時間。
方案2:ajax輪詢,隔幾秒發一個查詢,後臺記錄第一與最後一個查詢間隔時間。
方案3:關閉窗口或者跳轉的時候會觸發window.onbeforeunload函數,能夠在該函數中作處理(有兼容性問題);統計完數據記錄到本地cookies中,一段時間後統一發送。
複製代碼

瀏覽器內核有哪些,移動端用的是哪一個

Trident內核:IE,MaxThon,TT,The Word,360,搜狗瀏覽器等。[又稱爲MSHTML]
Gecko內核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey等;
Presto內核:Opera7及以上。[Opera內核原爲:Presto,現爲:Blink]
Webkit內核:Safari,Chrome等。[Chrome的:Blink(Webkit的分支)]

對於Android手機而言,使用率最高的就是Webkit內核。
複製代碼

其餘

至今遇到印象最深的bug(最好是搜索不到的)

印象最深的項目

是否瞭解最新技術,前端技術更新的見解

爲何要作前端

將來的職業規劃

平時是怎麼學習的

爲何選擇x公司

相關文章
相關標籤/搜索