1. TCP,UDP區別
TCP | UDP |
---|---|
基于有連接 | 基于無連接 |
對系統資源要求較多 | 對系統資源要求少 |
程序比較復雜 | 程序結構比較簡單 |
流模式 | 數據報模式 |
保證數據的準確性 | 不保證數據的準確性 |
保證數據的順序 | 不保證數據的順序 |
2. OSI七層模型以及tcp/ip四層模型
OSI七層模型 | tcp/ip四層模型 | 常用的5層模型 |
---|---|---|
物理層 | 物理層 | 物理層 |
數據鏈路層 | 數據層 | 數據鏈路層 |
網絡層 | 網絡層 | 網絡層(IP) |
傳輸層 | 應用層 | 傳輸層(TCP/UDP) |
會話層 | 應用層(HTTP協議) | |
表示層 | ||
應用層 |
3. Web前端應該從哪些方面來優化網站
- 頁面級別優化
- 資源合并
- 減少請求次數
- 圖片懶加載
- 圖片合并壓縮
- 腳本后置
- css前置
- inline腳本defer
- 域名配置時防止發生跳轉
- 避免重復打包模塊代碼
- 代碼級別優化
- 減少dom操作,virtual-dom的目標
- vue、 React底層優化
- css減少回流
- 根據viewport和渲染樹,進行幾何位置的計算
- 重繪: 是根據回流產生的幾何位置和渲染樹進行渲染.
- 回流一定重繪,重繪不一定回流
- 避免使用eval和Function
- 減少作用域鏈的查找
- jquery源碼,一開始使用一個立即執行函數,將window和undefined傳入到函數中,減少作用域鏈的查找
- CSS選擇符,瀏覽器對選擇符的解析是從右往左進行的
- 減少dom操作,virtual-dom的目標
4. 從輸入URL到頁面加載的過程
-
從瀏覽器接收到url到開啟網絡請求線程(這一部分開以展開瀏覽器的機制以及進程與線程之間的關系)
-
開啟網絡線程到發出一個完整的http請求(這一部分涉及DNF查詢,tcp/ip請求,五層因特網協議棧等知識)
-
從服務器接收到請求到對后臺接收到請求(這一部分涉及到負載均衡,安全攔截以及后臺內部的處理等等)
-
后臺和前臺的http交互(這一部分包括http頭部、響應碼、報文結構、cookie等知識,開源提下靜態資源的cookie優化,以及編碼,如gzip壓縮等)
-
單獨拎出來的緩存問題,http的緩存(這部分包括http緩存頭部,etag,catch-control等)
-
瀏覽器接收到http數據包的解析流程
- 詞法分析: 將html結構解析成dom樹
- 將css解析成css規則樹
- 合并DOM樹和CSS規則樹為一棵Render樹
- 然后回流: 根據渲染樹計算出渲染樹在視口(viewport)中的幾何位置
- 重繪: 根據渲染樹和幾何信息計算出準確位置之后交付給GPU進行繪制
-
CSS的可視化格式模型(元素的渲染規則,如包含塊、控制框,BFC,IFC等概念)
-
JS引擎解析過程(JS的解析階段,預處理階段,執行階段生成執行上下文,VO,作用域鏈,回收機制等等)
-
其他(可以擴展不同的知識模塊,如跨域、web安全,hybird模式等內容)
-
常見的三種跨域:
-
跨域: 瀏覽器處于安全考慮對非同源的js代碼進行限制
-
jsonp: 將回調函數的名稱放到url請求地址中,利用script標簽的src屬性不受瀏覽器請求的限制的特性.事先客戶端與服務器端的跨域
-
CORS: 跨域資源共享技術,在服務端設置:
Access-Control-Access-Origin
和Access-Control-Allow-Method: "get,post"
即可// 在express中使用路由守衛,設置返回頭部 app.use((req, res, next)=>{res.setHeader('Access-Control-Allow-Oring', '*');res.setHeader('Access-Control-Allow-Method': 'get, post') })
-
使用服務器代理: 簡單來說,就是瀏覽器會限制非同源的js代碼,但是服務器之間的交互是不會的.可以在本地的前端設置一個本地的服務器與非同源的服務器進行交互,然后將數據返回個前端.這樣就不會產生跨域了.
// 使用express實現本地的代理 // npm i request const express = require('express'); const app = express(); const request = require('request'); // 監聽本域的路由 app.get('/proxy',(req, res)=>{// 請求其他域的路由 request('http://www.google.com', function(error, response, body){res.send(body);}) }) app.listen(3000);
-
-
5. 如何在web端事先異步請求結果的復用,既只產生一次ajax請求并保證所有調用方法獲取到數據
- 較好的回答是: 緩存一個Promise對象,所有調用方注冊then函數
- localstorage(localstorage是否進程安全)
- 使用單例模式進行封裝
6. 文件上傳如何做斷電續傳 / 大文件上傳(了解)
- file reader: 文件分割
- localStorage: 存儲上傳信息
要點:
- 前端: 需要獲取文件的大小,去計算總分片數,并且需要校驗文件的合法性,在上傳過程中,需要即時的獲取到當前傳輸文件的當前分片數,以更新下次一需要傳輸文件的范圍大小;
- 服務端, 需要根據前端傳入的參數,去確定分析所屬的源文件,并追加
7.http2.0了解多少
延遲降低
: 針對HTTP高延遲的問題,SPDY優雅的采取了多路復用(multiplexing).多路復用通過多個stream共享一個tcp連接的方式,解決了HOL blocking的問題,降低了延遲同時提高了帶寬的利用率請求優先級(request prioritization)
: 多路復用帶來一個新的問題是,在連接共享的基礎上有可能會導致關鍵請求被阻塞.SPDY允許給每個request設置優先級,這樣重要的請求就會優先得到響應.比如瀏覽器加載首頁,首頁的html內容應該優先展示,之后才是各種靜態資源文件,腳本文件等加載,這樣可以保證用戶能第一時間看到頁面內容header壓縮
: 前端提到HTTP1.x的header很多時候都是重復多余的.選擇合適的壓縮算法可以減少包的大小和數量基于https的加密協議傳輸
: 大大提高了傳輸數據的可靠性服務器推送(server push)
: 采用了SPDY的網頁,例如我的網頁有一個style.css的請求,在客戶端收到style.css數據的同時,服務端會將style.js嗯等文件推送給客戶端,當客戶端再次嘗試獲取style.js時就可以直接從緩存中獲取到,不用再發送請求了.
8. HTTP2.0的多路復用和HTTP1.X中的長連接復用有什么區別?
HTTP/1.
一次請求-響應,建立一個連接,用完關閉;嗎每個請求都要建立一個連接HTTP/1.1
Pipeline解決方式,若個個請求排隊串行化單線程處理,后面的請求等待前面請求的返回才能獲得執行機會,一旦有某些請求超時等,后續請求只能被阻塞(線頭阻塞)HTTP/2
多個請求可同時再一個鏈接上并行執行。某個請求任務耗時嚴重,不會影響其他連接的正常執行
9. 你覺得http3.0用UDP協議會有什么好處和壞處
- 丟包重發需要確認,浪費至少一個ttfb
- 對連接中斷的感知會比tcp慢
- 丟包不影響后續數據傳輸
10. http緩存協議頭部字段
Cache-Control
: 響應頭表示資源是否可以被緩存,以及緩存的有效期Last-Modified
: 表示文件修改時間,請求頭為If-Modified-Since
:表示上次文件修改的時間Etag
: 表示文件版本,If-None-Match
: 表示上次下載文件的Etag
11. Etag和Last-Modified區別
Last-Modifiled
只能精確到秒,秒之間的內容更新Etag才能檢測- 文件有時會定時重新生成相同內容,
Last-Modified
不能很好辨別 - etag每次服務端生成都需要進行讀寫操作,而last-modified只需要讀取操作,etag的消耗更大
12. defer和async的區別
defer
要等到整個頁面再內存中正常渲染結束(DOM結構完全生成,以及其他腳本執行完成)才會執行,多個defer腳本會按照它們再頁面出現的順序加載(“渲染完再執行”)- async一旦下載完成,渲染引擎就會中斷渲染,執行這個腳本后,再繼續渲染.多個async腳本是不能保證加載順序的
【注】: 普通的script標簽再請求的時候就被阻塞了,而defer和async再請求的時候不會被阻塞
13. es6 module, commonjs, cmd, amd區別
- 說出cmd/amd的區別,引用依賴模塊方式
- 說出es6 module和commonjs的區別
commonJS模塊輸出的是一個值的拷貝,ES6模塊輸出的是值得引用.運行時加載,ES6模塊是編譯時輸出接口.ES6模塊的設計思想是盡量靜態化,使得編譯時就能確定模塊的依賴關系
14. xss和csrf攻擊原理,防御方法…
15. loadmore.js實現
16. Dom中Property和Attribute的區別
- property是DOM中的屬性,是JavaScript里的對象
- attribute是HTML標簽上的特性,它的值只能夠是字符串
17. 為什么[] ==(![]) 為true
18. reverse反轉字符串
let str1 = 'marron'
Array.from(str1).reverse()/* 注意不要使用下面的str1.split('').reverse()* 原因在于,字符串中可能出現長度不為1的字符.因此使用Array.from將字符串變為數組.* Array.from跟迭代器有關
*/
19. for、forEach、for…in、for…of的區別
-
forEach是數組的一個方法,掛在在原型鏈上
-
for…in: 會深度遍歷所有對象里面的可枚舉屬性.
-
栗子:遍歷對象中所有自己的屬性
for(let k in obj) {if(obj.hasOwnProperty(k)){console.log(obj[k])} }
-
-
for…of: ES6的特性.可以用在 字符串、數組、Map、Set, 不支持對象的遍歷
【注】: 下面寫法for循環效率最高
for(let i = arr.length -1; i>=0 ; i++){}
20. bind實現
- 函數式編程
- 柯里化
- instanceof 的原理
- new的原理
- 復雜this指向
- 原型鏈
- 閉包原理
- 作用域鏈
21. 對象深拷貝
22. debounce和throttle
- 防抖有2種
// 等待一段時間后執行
function debounce (handUp, fn){let timer = null;return function(){if(timer) clearTimeout(timer);timer = setTimeout(()=>{fn.call(this, arguments)}, handUp)}
}
// 先執行一次,然后再一段時間執行一次
function debounce1 (handUp, fn){let timer = null;return function(){if(timer) cleaerTimeout(timer)var flag = !timertimer = setTimeout(()=>{timer = null}, handUp)if(flag) fn.apply(this, arguments)}
}
23. 異步經典
console.log('script start')
async function async1(){await async2()console.log('async1 end')
}
async function async2(){console.log('async2 end')
}
async1()setTimeout(function(){console.log('setTimeout')
}, 0)new Promise(resolve =>{console.log('Promise')resolve()
})
.then(function(){console.log('promise1')
})
.then(function(){console.log('promise2')
})
console.log('script end')/*script startasync2 endPromisescript endasync1 endpromise1promise2setTimeout1. 事件循環種的任務分為: 宏任務和微任務.2. 當同步任務執行完畢后,會去異步隊列中尋找微任務.3. 微任務執行完畢后,再去宏任務隊列中尋找4. 微任務主要包括: Promise.then()、await后面的語句、process.nextTick(Node)、Object.observe、MutationObserve5. 宏任務主要包括: setTimeout、setInterval、setImmediate(Node)、requestAnimationFrame(瀏覽器)、I/O、UI rendering(瀏覽器)【版本】: 在Google瀏覽器73(金絲雀)版本之前,async的微任務是在promise的后面.因為源代碼實現給async包裹了3層.在73本版之后,Google給async進行了優化.會放在promise之前..*/
24. 說一下http和https
https的SSL加密是在傳輸層實現的
(1)http和https的基本概念
http:超文本傳輸協議,是互聯網上應用最為廣泛的一種網絡協議,是一個客戶端和服務器端請求和應答的標準(TCP),用于從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議,它可以使瀏覽器更加高效,使網絡傳輸減少
https: 是以安全為目標的HTTP通道,簡單講是HTTP的安全版,即HTTP下加入SSL層,HTTPS的安全基礎是SSL,因此加密的詳細內容就需要SSL
https協議的主要作用: 建立一個信息安全通道,來確保數組的傳輸,確保網站嗯等真實性
(2)http和https的區別?
http傳輸的數據都是未加密的,也就是明文的,網景公司設置了SSL協議來對http協議傳輸的數據進行加密處理,簡單來說https協議是由http和ssl協議構建的可進行加密傳輸和身份認真的網絡協議,比http協議安全性更高.
【主要區別如下】
- https協議需要ca證書,費用較高
- http是超文本傳輸協議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協議
- 使用不同的鏈接方式,端口也不同,一般而言,http協議的端口為80,https的端口為443
- http的連接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全
(3)https協議的工作原理
- 客戶端在使用https的url訪問服務器,則要求web服務器建立ssl連接
- web服務器接收到客戶端的請求之后,會將網站的證書(證書中包含了公鑰),返回或者說傳輸給客戶端
- 客戶端和web服務器端開始協商SSL鏈接的安全等級,也就是加密等級
- 客戶端瀏覽器通過雙方協商一致的安全等級,建立會話密鑰,然后通過網站的公鑰來加密會話密鑰,并傳送給網站.
- web服務器通過自己的私鑰解密出會話密鑰
- web服務器通過會話密鑰加密客戶端之間的通信
(4)https協議的優點
- 使用HTTPS協議可以認證用戶和服務器,確保數據發送到正確的客戶機和服務器;
- HTTPS協議是SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,要比http協議安全,可防止數據在傳輸過程中被竊取、改變,確保了數據的完整 性
- HTTPS是現行架構下最安全的解決方案,雖然不是絕對安全,但是大幅增加了中間人攻擊的成本
- 使用HTTPS協議的網站在搜索(Google2014年8月調整的搜索引擎算法)排名中普遍高于HTTP的網站
25. TCP的三次握手與四次揮手
三次揮手
- 參考
-
剛開始客戶端處于Closed狀態,服務端處于Listen狀態
-
第一次握手: 客戶端給服務端發送一個SYN報文,并指明序列號ISN?.然后客戶端進入 SYN_SEND狀態
- 此時攜帶的報文信息是 SYN =1, seq = x
-
第二次握手: 服務端接收到客戶端的SYN請求, 生成自己的序列號 ISN(s), 并計算下一個期待接收的報文的序列號,然后返回報文,此時服務器進入SYN_RCVD狀態
- 此時報文中攜帶的信息是: SYN =1 , ACK =1 , seq = y, ack= x+1
-
第三次握手: 客戶端接收到服務端的請求,生成服務端希望的下一個報文并返回,隨后進入ESTABLISHED狀態
- 此時報文中攜帶的信息是: ACK = 1, seq = x+1, ack = y+1
- 服務端收到這個報文后,也會進入ESTABLISHED狀態.隨即雙方開始傳遞數據
1. 為什么要三次握手,兩次不行嗎?
- 三次握手是確保連接建立的最少代價
- 假設采取2次:
- 假設客戶端發送一個連接請求c1
- 過了一段時間,由于沒有收到服務端的響應,客戶端重新發送一個報文請求c2
- 又過了一會兒,客戶端收到了服務端的響應s.(由于采取2次握手)故雙方開始傳遞數據,完事后斷開連接
- 由于網絡阻塞等其他原因.c1最終到達了服務端,服務端也很快的發送報文給客戶端,并且等待客戶端的數據
- 而客戶端因為數據傳輸完成了,并沒有開啟監聽服務端數據的服務.
- 這就造成了服務端一直等待客戶端傳輸數據的資源浪費
2. 什么是半連接隊列?
- 服務器第一次收到客戶端的請求后,會進入一個RCVD狀態,此時雙方還沒有建立連接,服務器會把此狀態下的連接放在一個隊列里,即半連接隊列
3. ISN(Initial Sequence Number)是固定的嗎?
- 當一端為建立連接而發送它的SYN時,它為連接選擇一個初始序號。ISN隨時間而變化,因此每個連接都將具有不同的ISN。
- ISN可以看作一個32比特的計數器,每4ms加1.
- 三次握手最重要的一點是客戶端與服務端交換ISN,以使對方知道接下來接收數據的時候,如何按照序號來組裝數據
4. 為什么第一、二次握手不允許攜帶數據
- 如果又人惡意攻擊服務器,那么他每次都會在第一次握中的SYN報文中放入大量的數據,來消耗服務器的資源
四次揮手
建立一個連接需要三次握手,而終止一個連接需要四次揮手,是由于TCP的半關閉造成的,即TCP提供了連接的一端在結束它的發送后還能接受來自另一端數據的能力.
graph TDsubgraph 客戶端C1(ESTABLISHED)C2(FIN_WAIT1)C3(FIN_WAIT2)C4(TIME_WAIT)C5(CLOSED)C1 --> C2C2 --> C3C3 --> C4C4 -->|等待2MSL| C5endsubgraph 服務器S1(ESTABLISHED)S2(CLOSE_WAIT)S3(LAST_ACK)S4(CLOSED)S1 --> S2S2 --> S3S3 --> S4endC1 --> |FIN = 1, seq = u|S1S1 --> |ACK = 1, seq = v, ack = u+1|C2S2 --> |FIN = 1, ACK = 1, seq = w, ack = u+1|C2C3 --> |ACK = 1, seq = u+1, ack = w+1|S4
剛開始, 雙方都處于ESTABLISHED狀態,假如是客戶端先發起的關閉請求:
- 第一次揮手: 客戶端發送FIN報文,此時客戶端處于FIN_WAIT1狀態,并停止發送數據
- 報文內容: FIN = 1 , seq = u
- 第二次揮手: 服務端接收到了來自客戶端的請求,會返回一個ACK報文,然后處于CLOSE_WAIT狀態
- 報文內容: ACK = 1, seq = v, ack = u +1
- 此時,客戶端接收到服務端傳遞的ACK報文后會進入FIN_WAIT2狀態
- 第三次揮手: 服務器數據傳輸完畢,發送一個FIN報文,然后關閉連接,進入LAST_ACK
- 報文內容: FIN = 1, ACK = 1, seq = w, ack = u + 1
- 第四次揮手: 客戶端接收到FIN報文后,會發送一個響應報文,隨機進入TIME_WAIT狀態.
- 報文內容: ACK = 1, seq = u+1, ack = w+1
- 服務端接收到ACK后,立即進入CLOSED狀態
1. 揮手為什么4次?
- 因為當服務端收到客戶端的SYN連接請求報文后,可以直接發送SYN+ACK。其中ACK報文是用來應答的,SYN報文是用來同步的.但是關閉連接時,當服務端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先返回一個ACK,告訴客戶端收到了客戶端的FIN報文.只有等所有數據傳輸完畢之后,服務端才會發送FIN報文
2. 四次揮手釋放連接時,等待 2MSL 的意義?
- MSL(Maximum Segment Lifetime)的英文縮寫,可譯為:最長報文壽命,它是任何報文在網絡上的存在的最長時間,超過這個時間報文將被丟棄.
- 為了保證客戶端發送的最后一個ACK報文段能夠到達服務器。因為這個ACK有可能丟失,從而導致處在LAST_ACK狀態的服務器收不到對FIN_ACK的確認報文。服務器會超時傳送這個FIN_ACK,接著客戶端再重傳一次確認,重新啟動時間等待計時器.最后客戶端和服務器都能正常的關閉.
- 假設客戶端在發送最后一個ACK報文后,立即進入關閉狀態,一旦這個ACK報文丟失后,服務端就無法進入正常關閉狀態.