東一榔頭西一棒槌的前端面試準備 - 基礎篇 (持續整理中...)

HTTP

GET和POST的區別

  • 報文格式不一樣,get把參數放在Url裏,post把參數放在body裏;
  • get請求因爲把全部參數都暴露在url裏,因此相對post安全性差一些;
  • url有長度限制,因此會限制get傳參(這條其實會根據瀏覽器的實現不一樣而不一樣);
  • get能夠被緩存能夠被收藏爲書籤,post不能;
  • get會被保存在瀏覽器歷史裏,post不會;
  • 回退或者前進的時候get是無害的,post會從新提交;

IP和TCP

IP: 互聯網的數據是經過數據包傳遞的,若是要將主機A的數據傳遞到主機B,就須要知道主機B的IP地址,才能正確尋址;額外的,數據包上還會添加上A的IP地址,這樣B才知道怎麼回覆A;可是,B拿到數據包以後,並不知道要交給哪一個程序進行處理,就須要UDP(用戶數據包協議)和TCP協議的幫助;
TCP(傳輸控制協議):上層把數據包傳遞給傳輸層 --> 傳輸層給數據包加上UDP頭交給網絡層 --> 網絡層把IP頭附加在數據包上,交給底層 --> 數據包被傳輸給了B的網絡層,這時候主機B把IP頭拆開,把數據包交給傳輸層 --> 傳輸層把UDP頭拆開,根據端口號交給相應的應用程序進行處理;
TCP的三次握手:主要是爲了確認通訊能力,也就是雙方都有發信和收信的能力,若是不確認的話任何數據傳送都是不穩定的~因此須要三次握手:
客戶端A向服務端B發送報文(B已確認了A的發信能力和B的收信能力) --> 服務端收到報文後,向客戶端發送報文(A已確認了雙方的收發能力) --> A返回ACK並創建鏈接(B確認了A的收信能力和B的發信能力)。TCP鏈接創建後,瀏覽器就能夠利用HTTP/HTTPS協議向服務器發送請求了。
TCP的四次揮手:因爲TCP協議有半關閉的狀態(就是隻能夠接收信息不能夠發生信息),關閉能夠由客戶端或者服務端提出:
二者在established狀態,客戶端A向服務端B提出關閉請求 --> B收到以後,給A發送收到信息的響應,同時通知應用程序關閉相關資源 --> B準備好了以後,給A發送關閉通知消息 --> A回覆B,斷開鏈接。javascript

緩存

DNS緩存

主要就是在瀏覽器本地把對應的 IP 和域名關聯起來,這樣在進行DNS解析的時候就很快。html

MemoryCache

存在內存裏的緩存。不會請求服務器。從優先級上來講,它是瀏覽器最早嘗試去命中的一種緩存。從效率上來講,它是響應速度最快的一種緩存。主要用來緩存圖片、字體、通常腳本等;和渲染進程「生死相依」,tab關掉就沒有了;前端

http緩存

  • 強緩存:不會請求服務器。expires和cache-control字段控制。expires依賴本地時間,因此並非最好的策略。cache-control: max-age=31536000比較合適。cache-control比expires優先度更高;
  • 協商緩存:依賴於服務端與瀏覽器之間的通訊。協商緩存機制下,瀏覽器須要向服務器去詢問緩存的相關信息,進而判斷是從新發起請求、下載完整的響應,仍是從本地獲取緩存的資源。若是服務端提示緩存資源未改動(Not Modified),資源會被重定向到瀏覽器緩存,這種狀況下網絡請求對應的狀態碼是 304。

協商緩存的實現,從Last-ModifiedEtag。Last-Modified 是一個時間戳,第一次請求的時候,服務器會返回Last-Modified,隨後咱們每次請求時,會帶上一個叫 If-Modified-Since 的時間戳字段, 服務器會進行比較;可是存在last-modified不許確的現象(好比咱們編輯了文件可是內容沒有發生改變,服務器只認修改的時間,所以會去修改last-modified的值,這樣的話就麼有正確使用協商緩存~),所以有了EtagEtag是由服務器爲每一個資源生成的惟一的標識字符串。vue

Service worker cache

Service Worker 是一種獨立於主線程以外的 Javascript 線程。它脫離於瀏覽器窗體,所以沒法直接訪問 DOM。這樣獨立的個性使得 Service Worker 的「我的行爲」沒法干擾頁面的性能,這個「幕後工做者」能夠幫咱們實現離線緩存、消息推送和網絡代理等功能。咱們藉助 Service worker 實現的離線緩存就稱爲 Service Worker Cache。java

Service worker

Service Worker
GoogleChrome關於service worker的sample.jsgit

service worker的由來和做用:

service worker是基於web worker發展而來的(web worker主要是由於js是單線程的,用ww能夠開闢一個新的線程,是脫離在主線程以外的,咱們能夠將複雜耗費時間的事情交給web worker來作)。sw是在ww的基礎上增長了離線緩存的能力。github

sw是由事件驅動的,具備生命週期,能夠攔截處理頁面的全部網絡請求(fetch),能夠訪問cache和indexDB,支持推送,而且可讓開發者本身控制管理緩存的內容以及版本,爲離線弱網環境下的 web 的運行提供了可能,讓 web 在體驗上更加貼近 native。換句話說他能夠把你應用裏的全部靜態動態資源根據不一樣策略緩存起來,在你下次打開時再也不須要去服務器請求,這樣一來就減小了網絡耗時,使得web應用能夠秒開,而且在離線環境下也變得可用。作到這一切你只須要增長一個sw文件,不會對原有的代碼產生任何侵入。web

// 頁面註冊service worker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js');
  });
}

service worker的生命週期:

最常綁定的事件:面試

  • install 事件中, 抓取資源進行緩存
  • activate 事件中, 遍歷緩存, 清除過時的資源
  • fetch 事件中, 攔截請求, 查詢緩存或者網絡, 返回請求的資源

ES6

let和const

class

函數(箭頭函數、參數解構)

Promise

async / await

Map和Set

Vue

爲何vue的列表渲染要加key?

React

Promise

跨域

js遵循同源策略,即同協議,同域名,同端口號,不然都算跨域。
下圖幫助理解:

能夠進行跨域的主要有iframe / JSONP / CORS算法

iframe

<iframe src="demo.html" height="300" width="500" name="demo" scrolling="auto" sandbox="allow-same-origin"></iframe>
  • window.self: 本身; window.parent: 父級窗口; window.top: 頂級窗口;
  • 在前端領域,咱們能夠經過window.top來防止咱們頁面被嵌套。
if(window != window.top){
    window.top.location.href = myURL;
}
  • iframe經過iframe.postMessage進行跨域通訊;經過window.addEventListener('message', fn)來監聽通訊事件;

閉包

原型鏈和class

瀏覽器相關

瀏覽器相關原理(面試題)詳細總結一

EventLoop

  • js是單線程的,會出現阻塞問題,所以有了異步隊列的出現
  • 主進程同步執行任務,異步操做將添加到異步隊列中
  • 等候主進程執行完畢後再執行異步隊列中的操做

什麼是宏任務和微任務?
異步隊列有宏任務和微任務之分。

  • 宏任務

    • setTimeout
    • setImmediate
    • setIntarval
    • requestAnimationFrame
    • I/O
    • UI rendering
  • 微任務

    • process.nextTick
    • Promise.then
    • Object.observe
    • MutationObserver
  • 一次事件循環:先運行宏任務隊列中的一個,而後運行微任務隊列中的全部任務。接着開始下一次循環

瀏覽器渲染過程

  • 解析HTML,構建DOM樹;
  • 解析CSS,生成CSS規則樹;
  • 合成HTML和CSS,生成render樹;
  • 佈局render樹,計算每個節點的位置和尺寸;
  • 繪製render樹(paint),繪製圖像信息;
  • 瀏覽器會把各層信息發給GPU,由GPU顯示在屏幕上;
從新佈局叫回流,就是改變佈局,每次的迴流都會觸發重繪(repaint), 又要去消耗gpu; 但並非每次repaint都會觸發reflow,好比改個背景色啥的,就不須要從新佈局;
onLoad: 在頁面全部文件加載完成後執行;DomContentLoaded: DOM加載後執行,沒必要等待樣式腳本和圖片下載;

webSocket

web Socket 協議

WebSocket 協議實現了瀏覽器與服務器全雙工通訊,能更好的節省服務器資源和帶寬並達到實時通信的目的。它與HTTP同樣經過已創建的TCP鏈接來傳輸數據,可是它和HTTP最大不一樣是:

  • WebSocket是一種雙向通訊協議。在創建鏈接後,WebSocket服務器端和客戶端都能主動向對方發送或接收數據,就像Socket同樣;
  • WebSocket須要像TCP同樣,先創建鏈接,鏈接成功後才能相互通訊。

WebSocket 鏈接必須由瀏覽器發起,請求協議是一個標準的HTTP請求(也就是說,WebSocket的創建是依賴HTTP的)。請求報文格式以下:
GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string // 用於標識這個鏈接
Sec-WebSocket-Version: 13 //指定了websocket的協議版本

web Socket API

建立web socket, 指定open、message等事件的回調便可(和web worker和service worker還挺像);
WebSocket 構造函數
const ws = new WebSocket('ws://localhost:8080/ws')
webSocket.readyState

CONNECTING: 值爲  0,表示正在鏈接。
OPEN: 值爲  1,表示鏈接成功,能夠通訊了。
CLOSING: 值爲  2,表示鏈接正在關閉。
CLOSED: 值爲  3,表示鏈接已經關閉,或者打開鏈接失敗。

webSocket.onopen : 指定鏈接成功以後的回調函數:

ws.onopen = function() {
    console.log('hello websocket')
}

webSocket.onclose: 指定鏈接關閉以後的回調函數
webSocket.onmessage: 指定收到服務器數據後的回調函數

webSocket.onmessage = function (event) {
    // 數據多是文本或者二進制數據
    if (typeof event.data === 'string') {
        //...
    } else if (event.data.instanceof ArrayBuffer) {
        //...
    }
    console.log(event.data)
}

webSocket.send: : 實例對象的send()方法用於向服務器發送數據
webSocket.send(message)

SPA和PWA

SPA的優缺點

從 SPA 到 PWA:Web App的下一站在哪?

微信小程序和PWA的異同點:

來自 微信小程序和PWA對比分析

二者和native app最大的區別都是「無需安裝、用完即走」

  • 小程序:主要依託微信自有生態,好處是幾乎不須要運營成本,且方便分享和傳播;同時,微信小程序相似於hybrid app的開發方式,用H5完成主要的渲染工做,原生層面上有WebView預加載,原生模塊覆蓋(camera/map/storage)等。壞處是微信出於穩定考慮沒有暴露DOM api, 且只能基於微信系統作個性化封裝,開發有必定的侷限性,小程序的生態也不是很好;
  • PWA:主要利用了service worker作緩存策略以及推送通知。優化了用戶的體驗,最大的限制就是看瀏覽器是否是支持service worker。

MVC和MVVM

MVC:

咱們全部的App都是界面和數據的交互,因此須要類來進行界面的繪製,因而出現了View,須要類來管理數據因而出現了Model。咱們設計的View應該能顯示任意的內容好比頁面中顯示的文字應該是任意的而不僅是某個特定Model的內容,因此咱們不該該在View的實現中去寫和Model相關的任何代碼,若是這樣作了,那麼View的可擴展性就至關低了。而Model只是負責處理數據的,它根本不知道數據到時候會拿去幹啥,可能拿去做爲算法噼裏啪啦去了,可能拿去顯示給用戶了,它既然沒法接收用戶的交互,它就不該該去管和視圖相關的任何信息,因此Model中不該該寫任何View相關代碼。然而咱們的數據和界面應該同步,也就是必定要有個地方要把Model的數據賦值給View,而Model內部和View的內部都不可能去寫這樣的代碼,因此只能新創造一個類出來了,取名爲Controller

這張圖把MVC分爲三個獨立的區域,而且中間用了一些線來隔開。頗有意思的設計,由於這些線彷佛出如今了駕校科目一的內容中,你瞧C和V以及C和M之間的白線,一部分是虛線一部分是實線對吧,這就代表了引用關係:C能夠直接引用V和M,而V和M不能直接引用C,至少你不能顯式的在V和M的代碼中去寫和C相關的任何代碼,而V和M之間則是雙黃線,沒錯,它們倆誰也不能引用誰,你既不能在M裏面寫V,也不能在V裏面寫M。哦,上面的描述有點小小的問題,你不是「不能」這樣寫,而是「不該該」這樣寫,沒人能阻止你在寫代碼的時候在一個M裏面去寫V,可是一旦你這樣作了,那麼你就違背了MVC的規範,你就不是在使用MVC了,因此這算是MVC的一個必要條件:使用MVC –> M裏面沒有V的代碼。因此M裏面沒有V的代碼就是使用MVC的必要條件。

MVVM:

MVVM的誕生:

就像咱們以前分析MVC是如何合理分配工做的同樣,咱們須要數據因此有了M,咱們須要界面因此有了V,而咱們須要找一個地方把M賦值給V來顯示,因此有了C,然而咱們忽略了一個很重要的操做:數據解析。在MVC出生的年代,手機APP的數據每每都比較簡單,沒有如今那麼複雜,因此那時的數據解析極可能一步就解決了,因此既然有這樣一個問題要處理,而面向對象的思想就是用類和對象來解決問題,顯然V和M早就被定義死了,它們都不該該處理「解析數據」的問題,理所應當的,「解析數據」這個問題就交給C來完成了。而如今的手機App功能愈來愈複雜,數據結構也愈來愈複雜,因此數據解析也就沒那麼簡單了。若是咱們繼續按照MVC的設計思路,將數據解析的部分放到了Controller裏面,那麼Controller就將變得至關臃腫。還有至關重要的一點:Controller被設計出來並非處理數據解析的。一、管理本身的生命週期;二、處理Controller之間的跳轉;三、實現Controller容器。這裏面根本沒有「數據解析」這一項,因此顯然,數據解析也不該該由Controller來完成。那麼咱們的MVC中,M、V、C都不該該處理數據解析,那麼由誰來呢?這個問題實際上在面向對象的時候至關好回答:既然目前沒有類可以處理這個問題,那麼就建立一個新的類出來解決不就行了?因此咱們聰明的開發者們就專門爲數據解析建立出了一個新的類: ViewModel。這就是MVVM的誕生。
相關文章
相關標籤/搜索