個人總結八股文的背誦方案
URL到顯示網頁的過程
- 瀏覽器解析URL,獲取協議,主機名,端口號,路徑等信息,并通過DNS查詢將主機名轉換為對應的IP地址
- 瀏覽器與服務器建立TCP,進行三次握手。
- 瀏覽器向服務器發送HTTP請求,包含請求方法 ,請求頭,請求體等信息
- 服務器接收并處理HTTP請求,根據請求的路徑和參數返回相應的HTTP響應,包含狀態碼,響應頭,響應體等信息
- 瀏覽器接收并解析HTTP響應,根據狀態碼和響應頭判斷響應的結果和類型
- 瀏覽器根據響應體的內容進行渲染和顯示。如果響應體是html文檔,瀏覽器會生成DOM樹和CSSOM樹,然后生成渲染樹,進行布局和繪制。如果響應體是js或css文件,則瀏覽器會執行js代碼或應用css樣式。如果響應體是圖片或其他資源,瀏覽器會下載并顯示。
- 瀏覽器會根據情況選擇關閉或保持TCP連接,進行四次揮手。
DNS查詢:本地域名服務器->host文件->根域名服務器->頂級域名服務器查詢->權限域名服務器查詢。(可以是遞歸查詢,也可以是迭代查詢)巧記:本地host根頂級權限
三次握手
- 客戶端隨機初始化序號seq=x,同時把 SYN 標志位設置為1,表示 SYN 報文。并發送給服務器
- 服務端收到客戶端的 SYN 報文后,隨機初始化序號seq=y,確認應答號ack=x+1;并將SYN 和 ACK 標志位都設置為1。發給客戶端
- 客戶端收到服務器的報文后,ack=y+1,seq = x+1。并發給服務器
seq=x,SYN=1;`` seq=y,ack=x+1,SYN=ACK=1; `` ack=y+1,seq = x+1。
為什么不能兩次或四次?
- 如果只有兩次握手,那么就無法保證雙方都能接收數據。例如,如果客戶端發送了連接請求后,由于網絡延遲或其他原因,沒有收到服務器的連接確認,那么客戶端就不知道服務器是否同意連接,也不知道服務器的初始序列號。如果此時客戶端開始發送數據,可能會導致服務器無法正確處理或丟棄數據。
- 如果有四次或更多次握手,那么就會浪費時間和資源。例如,如果在第二次握手后,服務器再向客戶端發送一個額外的確認,那么這個確認就是多余的,因為客戶端已經在第三次握手中確認了服務器的初始序列號。多余的握手會增加網絡負擔和延遲,并占用雙方的緩存空間。
四次揮手
- 客戶端發送SYN=1給服務器,之后客戶端進入 FIN_WAIT_1 狀態。
- 服務器發送ACK給客戶端,接著服務端進入 CLOSED_WAIT 狀態。客戶端收到服務端的 ACK 應答報文后,之后進入 FIN_WAIT_2 狀態。
- 服務端處理完數據后,向客戶端發送 FIN 報文,之后服務端進入 LAST_ACK 狀態。
- 客戶端收到服務端的 FIN 報文后,回一個 ACK 應答報文,之后進入 TIME_WAIT 狀態。
服務器收到了 ACK 應答報文后,就進入了 CLOSED 狀態,至此服務端已經完成連接的關閉。
客戶端在經過 2MSL 一段時間后,自動進入 CLOSED 狀態,至此客戶端也完成連接的關閉。
計算機網絡分層模型
- 物理層:物理媒介(雙絞線、光纖和無線電波)上傳輸比特流,并定義了物理設備的接口標準、電氣特性和編碼方式等。IEEE
- 數據鏈路層:相鄰節點之間傳輸幀,并提供差錯控制和流量控制。PPP、SLIP
- 網絡層:將數據報從源主機發送到目的主機,并提供路由選擇和擁塞控制。IP、ICMP、ARP
- 傳輸層:傳輸報文段,進程之間的通信。TCP和UDP
- 會話層:建立會話、session驗證,斷點傳輸。SMTP、DNS
- 表示層:數據轉換、加密、壓縮。TELNET、SNMP
- 應用層:用戶界面的交互。FTP,HTTP、NFS、SSL
上述是OSI七層模型,TCP/IP五層模型:應用層,表示層和會話層合并為應用層;TCP/IP四層模型:物理層和數據鏈路層合并為網絡接口層
TCP通信和UDP通信各自的優缺點
- TCP優點:可靠穩定,TCP通過三次握手建立連接,通過確認、重傳、窗口、擁塞機制等保證數據無差別、不丟失、不重復、按序到達。
缺點:效率低,占用系統資源高,易被攻擊。面向連接只能是點到點通信。 - UDP優點:效率高且安全。面向報文,可以進行一對多和多對多通信。
進程和線程的區別,加一點協程
- 資源:進程是資源分配的基本單位,而線程是操作系統調度和執行的基本單位。進程有自己獨立的地址空間和資源,而線程共享所屬進程的資源,但有自己的棧和局部變量。
- 開銷:進程的創建和銷毀都需要向操作系統申請或釋放資源,涉及到保存和恢復上下文,開銷較大。線程的創建和銷毀只需要在用戶空間內進行,涉及到部分上下文的切換,開銷較小。
- 通信:進程間通信需要借助操作系統提供的 IPC 機制,如管道、信號、消息隊列等。而線程間可以直接讀寫同一進程中的數據,只需要同步控制即可。
- 穩定性:進程之間是相互隔離的,一個進程崩潰不會影響其他進程的運行;線程之間是相互依賴的,一個線程崩潰可能導致整個進程終止。
- 協程是一種用戶態的輕量級線程,由程序員控制其創建、調度和銷毀,不需要操作系統的支持。協程之間是相互獨立的,一個協程崩潰不會影響其他協程的運行。
進程切換的過程
- 保存當前運行進程的上下文,包括程序計數器、棧指針、寄存器、內核數據結構等信息,以便下次恢復執行。
- 根據調度算法選擇一個就緒態的進程作為切換的進程。
- 恢復第一步保存的上下文,包括程序計數器、棧指針、寄存器、內核數據結構等信息。
- 轉移CPU的控制權給被選中的進程,開始執行。
進程間通信方式,線程多了全局變量
- 管道:半雙工通信方式,數據只能在父子進程間單向流動。
- 命名管道:有路徑名關聯,可以在任意進程間通信。
- 消息隊列:存放在內核中的消息鏈表,支持多個進程間通信
- 信號量:實現進程間的互斥與同步
- 共享內存:多個進程直接訪問同一塊物理內存空間。
陳述http
- HTTP,全稱為 HyperText Transfer Protocol,即為超文本傳輸協議。是互聯網應用最為廣泛的一種網絡協議
所有的 www 文件都必須遵守這個標準。 - http特性:無連接無狀態、構建于 TCP/IP 協議之上、默認端口號80、分為請求和響應兩個部分。
- 請求:GET,POST,PUT,DELETE
- 響應:200 OK、301永久重定向、302臨時重定向、304未修改、400客戶端語法錯誤、401未授權、403Forbidden 、404 Not Found、500服務器內部錯誤、503服務器暫時錯誤
- http缺點:通信使用明文,內容可能被竊聽。
通信雙方的身份無法得到認證,身份可能遭遇偽裝。
無法驗證報文的完整性。 - https可以簡單的理解為:https = http + 加密 + 認證 + 完整性保護。
- 完整性保護:對數據的散列值(哈希值)進行加密,然后將其附加在傳輸的數據上。接收方解密之后再驗證數據與散列值是否對應。
- 加密:SSL/TLS 使用公鑰加密和私鑰解密的方式來保護數據的機密性。
過程:S發公鑰給C,C用公鑰加密一個隨機生成的對稱密鑰,然后發給S,S用原有的私鑰來解密這個對稱秘鑰,之后C和S采用這個對稱秘鑰來加解密數據。
http有哪些版本?每個版本分別加了哪些新特性?
- HTTP 0.9:是第一個版本的HTTP協議,已過時。組成簡單,只有GET請求,且不支持請求頭,只支持純文本。HTTP 0.9具有典型的無狀態性,每個事務獨立進行處理,事務結束時就釋放這個連接。
- HTTP 1.0:
引入了請求方法,GET、HEAD、POST,開始支持客戶端通過POST方法向Web服務器提交數據
引入了內容協商,用于讓客戶端和服務器協商最合適的內容格式,如語言、字符集、編碼等。
引入了狀態碼、頭部字段、短連接和緩存機制。 - HTTP 1.1:
引入了請求方法,OPTIONS, PUT, DELETE, TRACE, CONNECT方法
引入了管道機制,允許客戶端在收到上一個響應之前就發送下一個請求,進一步減少了網絡延遲。
引入了分塊傳輸編碼,將內容分成多個塊發送,每個塊包含自己的大小信息。
完善緩存機制,加入了一些cache的新特性,引入了實體標簽,一般被稱為e-tags,新增更為強大的Cache-Control頭。
引入了持久連接、引入虛擬主機:在同一個IP地址和端口上提供多個不同域名的服務 - HTTP2.0
引入了二進制分幀,信息分割為更小的幀,并采用二進制編碼,從而降低了報文解析的復雜度和開銷。
引入了多路復用,在同一個TCP連接上同時發送和接收多個請求和響應
引入了首部壓縮,通過HPACK算法對請求和響應的頭部字段進行壓縮。
引入了服務器推送,服務器可以在客戶端請求之前主動發送數據,預加載一些客戶端可能需要的資源。
引入了優先級和流量控制,即客戶端和服務器可以為不同的請求設置優先級,讓重要的請求優先處理,同時可以控制數據流的速度,避免擁塞和浪費。 - HTTP 3.0
使用QPACK算法對HTTP頭部進行壓縮,提高了編碼效率和壓縮率。
使用QUIC協議代替TCP協議,實現了無序、并發的字節流傳輸,解決了隊頭阻塞問題。
0-RTT握手:允許客戶端在第一次請求時就發送數據。
WebSocket
- 實時性:WebSocket允許服務器主動向客戶端推送數據,實現實時通信,無需客戶端發起請求。
- 全雙工通信:WebSocket允許客戶端和服務器同時發送和接收數據,實現真正的雙向通信。
- 較低的延遲:由于WebSocket在建立連接后保持長連接,減少了連接和關閉的開銷,因此具有較低的延遲。
- 較低的延遲:由于WebSocket在建立連接后保持長連接,減少了連接和關閉的開銷,因此具有較低的延遲。
- 跨域支持:WebSocket支持跨域通信,不受同源策略限制。
強緩存和協商緩存
- 強緩存:當緩存未過期時,直接從本地緩存中加載資源。字段包括 Expires(HTTP/1.0)和 Cache-Control(HTTP/1.1)
- 協商緩存:本地緩存已過期,則發請求詢問服務器資源是否有更新;服務器根據 Last-Modified 或 ETag 來判斷,若未更新則返回304 Not Modified 狀態碼繼續使用本地資源,否則返回200狀態碼和新的資源。
ARQ協議
- 自動重傳請求協議,是一種用于實現可靠數據傳輸的協議。它通過使用確認和超時這兩個機制,在不可靠服務的基礎上實現可靠的信息傳輸。如果發送方在發送后一段時間之內沒有收到確認幀,它通常會重新發送。
- 停止等待ARQ協議:是指發送方每發送一個分組就停止發送,等待接收方的確認。如果發送方在超時時間內沒有收到確認,就重發該分組。這種協議簡單易實現,但信道利用率較低。
- 連續ARQ協議:是指發送方可以連續發送多個分組,不必每發完一個分組就停頓下來等待對方的確認。這樣可以提高信道利用率,但也增加了復雜性和開銷。連續ARQ協議又分為回退N幀ARQ協議和選擇重傳ARQ協議。
- 回退N幀ARQ協議:某個分組出錯或丟失,就丟棄該分組及其后續的分組。選擇重傳ARQ協議:某個分組出錯或丟失,就緩存該分組之后正確接收的分組,并對每個正確接收的分組單獨發送選擇性確認。
常見的攻擊類型CSRF,XSS,DDoS,點擊劫持,中間人攻擊,DNS 劫持
- CSRF:用戶未退出網站A,同一個瀏覽器中訪問網站B,網站B攜帶cookie向網站A發送請求獲取用戶信息,網站A根據cookie會響應該請求。解決方法:服務器進行同源檢測、設置http-only:true,驗證Token。
- XSS:存儲型、反射型、DOM。存儲型:將惡意代碼提交到服務器;反射型:惡意代碼放在URL;DOM:通過惡意腳本修改頁面的 DOM 結構。解決方法:對用戶輸入進行編碼、校驗過濾特殊字段、保護cookie
- ddos:多個設備向目標服務器發送大量請求,導致目標服務器無法正常提供服務或者奔潰。解決方法:限制ip訪問頻率、使用負載均衡和緩存、使用CDN、云防火墻等第三方防御服務。
- 點擊劫持:通過透明的iframe或其他可點擊元素覆蓋在目標網站上,欺騙用戶點擊來竊取用戶信息。解決方法:設置 X-Frame-Options 響應頭(DENY、SAMEORIGIN、SAMEORIGIN)是否允許其他網頁的iframe顯示、js檢測是否嵌套其他網頁,選擇跳出或提示用戶。
- 中間人攻擊:在用戶和目標網站之間截取通信信息,獲取用戶敏感信息或篡改數據。解決方法:HTTPS協議、避免使用公共wifi。
- DNS劫持:篡改DNS服務器或本地hosts文件,使得用戶訪問的域名解析到別的ip地址,從而訪問到假冒的網站。解決方法:時刻手動維護本地hosts文件,使用可靠的 DNS 服務器。
JavaScript 的事件循環機制
- js是單線程的,如果遇到異步任務,如 setTimeout、Promise、Ajax 等,就會將它們放入一個任務隊列中,等待當前的同步任務執行完畢后,再按照一定的規則從任務隊列中取出異步任務執行。這個過程就是事件循環。
- 同步代碼執行完畢時,事件循環會檢查微任務隊列并依次執行完,然后會檢查宏任務隊列并依次執行完。
- 宏任務包括 setTimeout、setInterval、Dom事件、setImmediate、requestAnimationFrame、I/O、UI rendering 等,微任務包括 Promise、async/await、MutationObserver、process.nextTick 等。
JavaScript new的過程
- 創建一個空的簡單 JavaScript 對象(即 {} );
- 將這個空對象的原型指向構造函數的原型,即設置 proto 屬性;
- 將這個空對象作為 this 的上下文傳遞給構造函數,并執行構造函數中的代碼;
- 如果構造函數沒有顯式返回一個對象(返回的是基本類型也不行),則返回這個空對象,否則返回構造函數返回的對象。
說一下Chrome的進程架構
- 瀏覽器進程:負責界面顯示、用戶交互、子進程管理,同時提供存儲等功能。
性能優化
- 訪問網站前:
(1) 推送資源:預先將頁面資源如JS,圖片,多媒體文件推送到客戶端/瀏覽器
(2) 預加載: prefetch(可能使用的資源)、preload(必要資源)、prerender
(3) 預先請求AJAX:提前獲取下個跳轉頁面需要的ajax數據,緩存到localstorage - 加載過程中:
(1) 查詢強緩存:service worker、強緩存
(2) 解析dns:
(3) 建立tcp鏈接:http1.1持久鏈接、http2多路復用
(4) 發送請求: 精靈圖、disk cache協商緩存、小圖片base64免去請求
(5) 解析html:css在上,js在下避免阻塞
(6) 構建渲染樹:減少DOM的數量和嵌套層級、減少重繪重排、懶加載
(7) 運行JS:精簡代碼、代碼分割、tree shaking - 頁面運行時:
(1) 虛擬滾動條應對無限加載
(2) 節流防抖
(3) 內存:避免全局變量、避免使用閉包、手動回收(obj=null)
同源策略與跨域 https://www.nowcoder.com/discuss/514959073205370880
- 域名、協議、端口號任意一個不同則為跨域。
- 解決跨域:JSONP(script標簽可以跨域加載資源)、CORS(Cross-Origin Resource Sharing、服務端響應頭"Access-Control-Allow-Origin")、代理服務器、WebSocket協議不受同源策略限制、postMessage
XMLHttpRequest 和 fetch 區別 https://blog.csdn.net/weixin_43073401/article/details/132001688
- 用法:xhr用法比較復雜,依次創建對象、設置請求屬性、監聽狀態變化、發送請求;fetch 比較簡單,只需要調用fetch函數并傳入參數即可
- 返回值:xhr返回的是xhr對象,通過responseText 或 responseXML獲取數據;fetch返回一個Promise 對象,通過response.json() 或 response.text()獲取數據
- 跨域請求:xhr跨域時需要設置withCredentials為 true,同時服務器端需要設置允許跨域請求的頭信息。fetch默認不會發送cookie,可設置 credentials: ‘include’ 來攜帶Cookie。'omit’不會攜帶cookie,'same-origin’同源時攜帶cookie
- 錯誤處理:xhr可以通過onerror 和 onreadystatechange 等事件來處理錯誤;fetch需要手動檢查響應的 ok 屬性來處理錯誤
- 兼容性:xhr支持廣泛,包括老舊瀏覽器;fetch 是ES6的新特性,不支持IE瀏覽器(除了Edge)和一些舊版本瀏覽器,但可以通過polyfill來實現兼容。
異步加載js https://www.jb51.net/article/107680.htm
- 給 script 標簽添加 async 屬性:異步加載腳本,加載完成后立即執行,加載順序并不是固定的。
- 給 script 標簽添加 defer 屬性:異步加載腳本,文檔解析完成后執行,按照在頁面中出現的順序執行。
- JavaScript動態創建
Session、Cookie和Token https://www.nowcoder.com/discuss/515115466998734848
- Session是服務器端的會話狀態管理機制,首次訪問服務器時會創建一個唯一的session id通過Set-Cookie返回給客戶端,存儲在服務器內存或數據庫占用服務器資源。
- Token是身份驗證和授權的令牌,由服務器生成發給客戶端,不依賴于服務器的會話存儲。
- Cookie是存儲在瀏覽器中的文本文件,后續的請求會攜帶相應的cookie信息,由于存在客戶端,所以存在被篡改和劫持的風險。
- cookie屬性:name、value、domain、path、expires或max-age、secure(HTTPS)、HttpOnly、SameSite:(“Strict”、“Lax"或"None”)。
ES6及以上新特性
- ES6:let,const、箭頭函數、模板字符串、解構賦值、擴展運算符、默認參數值、類和繼承、Promise、Set 和 Map 、Symbol
- ES7:數組includes、指數操作符(**)
- ES8:async/await、values/entries、padStart/padEnd、函數參數列表結尾允許逗號、Object.getOwnPropertyDescriptors()
- ES9:異步迭代器、Promise.finally()、Rest/Spread 屬性、正則表達式命名捕獲組/反向斷言/dotAll模式
- ES10:flat扁平化、flatMap映射數組、trimStart/trimEnd、String.prototype.matchAll、Symbol.prototype.description、Object.fromEntries()、JSON Superset 超集、JSON.stringify() 加強格式轉化、Array.prototype.sort() 更加穩定、Function.prototype.toString() 重新修訂
- ES11:可選鏈操作符(?.)、空位合并操作符(??)、動態 import ()、BigInt、globalThis、Promise.allSettled、for in 結構
- ES12:replaceAll、Promise.any、邏輯賦值操作符 ??=、&&=、 ||=、WeakRef(ref.deref())、數字下劃線分隔符、Intl.ListFormat、Intl.DateTimeFormat
- ES13:類私有方法和字段(#前綴)、可索引數據上新增.at()方法、Object.hasOwn(object, property)
require和import區別:
- import是ES6語法,require是commonJS語法。
- 導入文件類型:import只能導入ES6模塊或者使用Babel等工具轉化為ES6模塊的代碼,而require可以導入CommonJS模塊、AMD模塊、UMD模塊以及Node.js內置模塊等多種類型的模塊。
- 變量提升:import語句是靜態執行的(import()是運行時執行,動態導入),并在模塊內部創建一個局部作用域,不會變量提升,因此需要將語句放在文件頂部;require函數是動態執行的,這意味著它在運行時執行,可以變量提升。
- 導出方式:import對應的導出為export xxx 或export default {};而require對應的導出為module.exports = {};
- 導入內容:require 請求整個包對象,import 只請求模塊中需要的部分;
瀏覽器的前端存儲方案
- cookies:Cookies 可以用于存儲少量數據,并且有一定的過期時間,但由于每次請求都會攜帶 Cookies,所以不適合存儲大量數據。
- Web Storage(localStorage 和 sessionStorage)
- IndexedDB:是一種客戶端數據庫,可以在瀏覽器中存儲大量結構化數據。它提供了類似于 SQL 的查詢功能,并且數據可以持久化保存在客戶端。
- Cache Storage:是 Service Worker 的一部分,用于緩存網絡請求的數據,可以實現離線訪問和提高應用性能
- WebSQL(已廢棄):是一種在客戶端使用 SQL 數據庫的方案,但已被廢棄,不推薦使用。
js設計模式
- 單例模式:確保一個類只有一個實例,并提供一個全局訪問點。用來管理全局狀態、配置等。
- 觀察者模式:定義了一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都會收到通知并自動更新。
- 發布訂閱模式:在觀察者模式基礎上解耦了發布者(Publisher)和訂閱者(Subscriber),通過一個消息中心作為媒介。
- 策略模式:一個功能有多種方案可以選擇,封裝各個方案,并且使他們能互相替換。(抽取公共邏輯)
- 代理模式:為其他對象提供一種代理以控制對這個對象的訪問。保護代理、虛擬代理、緩存代理
- 迭代器模式:提供一種方法順序訪問一個聚合對象中的各個元素,而又不需要暴露該對象的內部表示。如js的forEach、map、some等(Iterator和 Generator)
- 適配器模式:解決兩個接口/方法間的接口不兼容的問題。
- 享元模式:大量相似對象,抽出共同部分屬性作為內部狀態,其他屬性作為外部狀態。(抽取公共屬性)
- 裝飾器模式:在不改變原有對象結構的基礎上,動態地給對象增加新的功能或者增強原有功能。(高階組件)