?URL從輸入到頁面展示的過程
版本1
1.用戶在瀏覽器的地址欄輸入訪問的URL地址。瀏覽器會先根據這個URL查看瀏覽器緩存-系統緩存-路由器緩存,若緩存中有,直接跳到第6步操作,若沒有,則按照下面的步驟進行操作。
2.瀏覽器根據輸入的URL地址解析出主機名。
3.瀏覽器將主機名轉換成服務器ip地址。瀏覽器先查找本地DNS緩存列表,看緩存里面是否存在這個ip,如果有則進入第4步,如果緩存中不存在這個ip地址,就再向瀏覽器默認的DNS服務器發送查詢請求,同時緩存當前這個ip到DNS緩存列表中。
4.拿到ip地址后,瀏覽器再從URL中解析出端口號。
5.拿到ip和端口后,瀏覽器會建立一條與目標Web服務器的TCP連接,也就是傳說中的三次握手。
6.瀏覽器向服務器發送一條HTTP請求報文。
7.服務器向瀏覽器返回一條HTTP響應報文。
8.關閉連接,瀏覽器解析HTML、CSS、JS等資源,最后進行頁面渲染,呈現給用戶。
版本2
先進行DNS域名解析,先查看本地hosts文件,查看有沒有當前域名對應的ip地址,若有直接發起請求,沒有的話會在本地域名服務器去查找,該查找屬于遞歸查找,如果本地域名服務器沒查找到,會從根域名服務器查找,該過程屬于迭代查找,根域名會告訴你從哪個與服務器查找,最后查找到對應的ip地址后把對應規則保存到本地的hosts文件中。
如果想加速以上及之后的http請求過程的話可以使用緩存服務器CDN,CDN過程如下:
用戶輸入url地址后,本地DNS會解析url地址,不過會把最終解析權交給CNAME指向的CDN的DNS服務器
CDN的DNS服務器會返回給瀏覽器一個全局負載均衡IP
用戶會根據全局負載均衡IP去請求全局負載均衡服務器
全局負載均衡服務器會根據用戶的IP地址,url地址,會告訴用戶一個區域負載均衡設備,讓用戶去請求它。
區域負載均衡服務器會為用戶選擇一個離用戶較近的最優的緩存服務器,并把ip地址給到用戶
用戶想緩存服務器發送請求,如果請求不到想要的資源的話,會一層層向上一級查找,知道查找到為止。
進行http請求,三次握手四次揮手建立斷開連接
服務器處理,可能返回304也可能返回200
返回304說明客戶端緩存可用,直接使用客戶端緩存即可,該過程屬于協商緩存
返回200的話會同時返回對應的數據
客戶端自上而下執行代碼
其中遇到CSS加載的時候,CSS不會阻塞DOM樹的解析,但是會阻塞DOM樹的渲染,并且CSS會阻塞下面的JS的執行
然后是JS加載,JS加載會影響DOM的解析,之所以會影響,是因為JS可能會刪除添加節點,如果先解析后加載的話,DOM樹還得重新解析,性能比較差。如果不想阻塞DOM樹的解析的話,可以給script添加一個
defer或者
async的標簽。
defer:不會阻塞DOM解析,等DOM解析完之后在運行,在
DOMContentloaed
之前async: 不會阻塞DOM解析,等該資源下載完成之后立刻運行
進行DOM渲染和Render樹渲染
獲取html并解析為Dom樹
解析css并形成一個cssom(css樹)
將cssom和dom合并成渲染樹(render樹)
進行布局(layout)
進行繪制(painting)
回流重繪
回流必將引起重繪,重繪不一定引起回流
什么是重繪?回流(重排)?
1.?當頁面中的一部分(或全部)因為元素的規模尺寸,布局,隱藏等改變而需要重新構建。這就稱為回流。每個頁面至少需要一次回流,就是在頁面第一次加載的時候。
2.?當頁面中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響布局的,比如background-color。則就叫稱為重繪。
注:回流必將引起重繪,而重繪不一定會引起回流。
//什么時候會發生回流?
當頁面布局和幾何屬性改變時候就需要回流。下面的情況會引發瀏覽器的回流:
1:添加或者刪除可見的DOM元素
2:元素位置改變;
3:元素尺寸改變----邊距、填充、邊框、高度和寬度
4:內容改變---比如文本改變或者圖片大小改變而引起的計算值寬度和高度改變
5:頁面渲染初始化
6:瀏覽器窗口尺寸改變---resize事件發生時
//什么時候發生重繪?
1.改變字體
2.增加或者移除樣式表
3.內容變化(input框輸入文字)
4.激活css偽類????eg???:hover
5.計算offsetWidth、offsetHeigth屬性(瀏覽器的可見高度)
6.設置style屬性的值
//如何減少回流、重繪
1.使用DocumentFragment進行緩存操作,引發一次回流和重繪
2.?csstext(利用cssText屬性合并所有改變,然后一次性寫入)
3.使用trsansform使用改變位置(margin-left等)這些更加流暢
4.如果你要改變多個屬性,最好將這些屬性定義在一個class中,直接修改class名,這樣只用引起一次回流。
防抖和節流
//函數防抖:當事件被觸發一段時間后再執行回調,如果在這段時間內事件又被觸發,則重新計時。
在事件觸發時,開始計時,在規定的時間(delay)內,若再次觸發事件,將上一次計時(timer)清空,然后重新開始計時。保證只有在規定時間內沒有再次觸發事件之后,再去執行這個事件。?1次
//函數節流(throttle):指定時間間隔內,若事件被多次觸發,只會執行一次
在事件觸發之后,開始計時,在規定的時間(delay)內,若再次觸發事件,不對此事件做任何處理。保證在規定時間內只執行一次事件.
//函數防抖的應用場景
連續的事件,只需觸發一次回調的場景有:
????搜索框搜索輸入。只需用戶最后一次輸入完,再發送請求
????手機號、郵箱驗證輸入檢測
????窗口大小Resize。只需窗口調整完成后,計算窗口大小。防止重復渲染。
//函數節流的應用場景
間隔一段時間執行一次回調的場景有:
????滾動加載,加載更多或滾到底部監聽
????谷歌搜索框,搜索聯想功能
????高頻點擊提交,表單重復提交
深/淺拷貝
淺拷貝--新舊互相影響,改變的是地址
??新值===原值,?只能拷貝一層
????>?1.?數組方法?`slice截取`,?`concat拼接`,?`filter過濾`?,?`map`,
????>?2.?對象方法?`Object.assign({?},obj)`,?
????>?3.?展開運算符`{…obj}`
深拷貝--新舊互不影響,改變的是值
??新值=/=原值?,?可以拷貝多層
????>?1.?JSON序列化?**JSON.parse(?JSON.stringify(obj)?)**?對象-->字符串-->對象
??????缺陷:1.如果對象里有RegExp對象,則序列化的結果將只得到空對象;
????????2.如果對象里有函數,undefined,則序列化的結果會把函數或?undefined丟失;
??????????????????3.對象中含有NaN,則序列化的結果會變成null
????>?2.?原生實現
????>?-?遞歸
?????//?遞歸實現深拷貝
????????????function?cloneDeep(obj)?{
??????????????//?1.根據obj為對象或者數組,產生一個空的對象或數組,存放數據
??????????????var?newobj?=?obj?instanceof?Array???[]?:?{},
??????????????//?2.for...in進入循環
??????????????for?(var?k?in?obj)?{
????????????????//?3.判斷對象的第一個屬性是否為數組或者對象,如果是,則進入遞歸
??????????????if?(typeof?obj[k]?===?'object')?{
?????????????????newobj[k]?=?cloneDeep(obj[k])
???????????????}?else?{
?????????????????//?4.如果數據為基本類型,則直接賦值
?????????????????newobj[k]?=?obj[k]
???????????????}
?????????????}
?????????????//?5.把存放了數據的新對象返回出去
?????????????return?newobj
???????????}????
????>?3.?工具實現【?第三方封裝庫?】
????>?-?loadsh?_.cloneDeep(obj)
????>?-?缺點
????>?-?Immutable
????4.Object.create()
js數據類型
基本數據類型有:Number、String、Boolean、Null、Undefined、Symbol(ES6新增數據類型)、bigInt
引用數據類型統稱為Object類型,細分有:Object、Array、Date、Function、RegExp
基本數據類型的數據直接存儲在棧中;而引用數據類型的數據存儲在堆中,每個對象在堆中有一個引用地址。引用類型在棧中會保存他的引用地址,以便快速查找到堆內存中的對象。
棧內存是自動分配內存的。而堆內存是動態分配內存的,不會自動釋放。所以每次使用完對象的時候都要把它設置為null,從而減少無用內存的消耗
判斷數據類型有幾種方法:
typeof:
缺點是typeof null
的值為Object
,無法分辨是null
還是Object
instanceof:
缺點是只能判斷對象是否存在于目標對象的原型鏈上(原理是實際上就是查找目標對象的原型鏈)
constructor
Object.prototype.toString.call()
一種最好的基本類型檢測方式
Object.prototype.toString.call()
;它可以區分 null 、 string 、boolean 、 number 、 undefined 、 array 、 function 、 object 、 date 、 math 數據類型。
缺點:不能細分為誰誰的實例
什么是閉包,閉包的作用?
函數執行,形成私有的執行上下文,使內部私有變量不受外界干擾,起到保護和保存的作用
作用:
保護:避免命名沖突
保存:解決循環綁定引發的索引問題
變量不會銷毀:可以使用函數內部的變量,使變量不會被垃圾回收機制回收
應用:
設計模式中的單例模式
for循環中的保留i的操作
防抖和節流
函數柯里化
缺點:會出現內存泄漏的問題
https和http有什么區別,https的實現原理?
http無狀態無連接,而且是明文傳輸,不安全
https傳輸內容加密,身份驗證,保證數據完整性
https實現原理:
首先客戶端向服務端發起一個隨機值,以及一個加密算法
服務端收到后返回一個協商好的加密算法,以及另一個隨機值
服務端在發送一個公鑰CA
客戶端收到以后先驗證CA是否有效,如果無效則報錯彈窗,有過有效則進行下一步操作
客戶端使用之前的兩個隨機值和一個預主密鑰組成一個會話密鑰,在通過服務端傳來的公鑰加密把會話密鑰發送給服務端
服務端收到后使用私鑰解密,得到兩個隨機值和預主密鑰,然后組裝成會話密鑰
客戶端在向服務端發起一條信息,這條信息使用會話秘鑰加密,用來驗證服務端時候能收到加密的信息
服務端收到信息后返回一個會話秘鑰加密的信息
都收到以后SSL層連接建立成功
http緩存
緩存分為強緩存和協商緩存
強緩存
在瀏覽器加載資源時,先看看
cache-control
里的max-age
,判斷數據有沒有過期,如果沒有直接使用該緩存 ,有些用戶可能會在沒有過期的時候就點了刷新按鈕,這個時候瀏覽器就回去請求服務端,要想避免這樣做,可以在cache-control
里面加一個immutable
.public
允許客戶端和虛擬服務器緩存該資源,cache-control中的一個屬性
private
只允許客戶端緩存該資源
no-storage
不允許強緩存,可以協商緩存
no-cache
不允許緩存
協商緩存
瀏覽器加載資源時,沒有命中強緩存,這時候就去請求服務器,去請求服務器的時候,會帶著兩個參數,一個是
If-None-Match
,也就是響應頭中的etag
屬性,每個文件對應一個etag
;另一個參數是If-Modified-Since
,也就是響應頭中的Last-Modified
屬性,帶著這兩個參數去檢驗緩存是否真的過期,如果沒有過期,則服務器會給瀏覽器返回一個304狀態碼,表示緩存沒有過期,可以使用舊緩存。 etag的作用
有時候編輯了文件,但是沒有修改,但是
last-modified
屬性的時間就會改變,導致服務器會重新發送資源,但是etag
的出現就完美的避免了這個問題,他是文件的唯一標識緩存位置:
內存緩存Memory-Cache
離線緩存Service-Worker
磁盤緩存Disk-Cache
推送緩存Push-Cache
面試官:localStorage、SessionStorage、cookie、session 之間有什么區別
localStorage:
關閉瀏覽器后數據依然保留,除非手動清除,否則一直在,相同瀏覽器的不同標簽在同源情況下可以共享localStorage
sessionStorage:
關閉瀏覽器或者標簽后即失效,只在當前標簽可用,當前標簽的iframe中且同源可以共享
cookie:
是保存在客戶端的,一般由后端設置值,可以設置過期時間
儲存大小只有4K
一般用來保存用戶的信息的
在http下cookie是明文傳輸的,較不安全
cookie屬性有
http-only:不能被客戶端更改訪問,防止XSS攻擊(保證cookie安全性的操作)
Secure:只允許在https下傳輸
Max-age: cookie生成后失效的秒數
expire: cookie的最長有效時間,若不設置則cookie生命期與會話期相同
session:
session是保存在服務端的
session的運行依賴sessionId,而sessionId又保存在cookie中,所以如果禁用的cookie,session也是不能用的,不過硬要用也可以,可以把sessionId保存在URL中
session一般用來跟蹤用戶的狀態
session 的安全性更高,保存在服務端,不過一般為使服務端性能更加,會考慮部分信息保存在cookie中
localstorage存滿了怎么辦?
劃分域名,各域名下的存儲空間由各業務組統一規劃使用
跨頁面傳數據:考慮單頁應用、采用url傳輸數據
最后兜底方案:調別人的存儲
怎么使用cookie保存用戶信息
document.cookie(“名字 = 數據;expire=時間”)
怎么刪除cookie
目前沒有提供刪除的操作,但是可以把它的Max-age設置為0,也就是立馬失效,也就是刪除了