挑戰一輪大廠後的面試總結 (含六個方向) - 瀏覽器 篇

在去年末開始換工做,直到如今算是告了一個段落,斷斷續續的也面試了很多公司,如今回想起來,那段時間經歷了被面試官手撕,被筆試題狂懟,悲傷的時候差點留下沒技術的淚水。javascript

這篇文章我打算把我找工做遇到的各類面試題(每次面試完我都會總結)和我本身複習遇到比較有意思的題目,作一份彙總,年後是跳槽高峯期,也許能幫到一些小夥伴。css

先說下這些題目難度,大部分都是基礎題,由於這段經歷給個人感受就是,無論你面試的是高級仍是初級,基礎的知識必定會問到,甚至會有必定的深度,因此基礎仍是很是重要的。html

我將根據類型分爲幾篇文章來寫:前端

面試總結:javascript 面試點彙總(萬字長文)(已完成) 【強烈你們看看這篇,面試中 js 是大頭】vue

面試總結:nodejs 面試點彙總(已完成)html5

面試總結:瀏覽器相關 面試點彙總(已完成)java

面試總結:css 面試點彙總(已完成)node

面試總結:框架 vue 和工程相關的面試點彙總(已完成)jquery

面試總結:非技術問題彙總(已完成)css3

我會抓緊時間把未完成的總結補全的~

這篇文章是對 瀏覽器 相關的題目作總結,歡迎朋友們先收藏在看。

先看看目錄

目錄

介紹下緩存

全部的性能優化中,緩存是最重要也是最直接有效的,畢竟如今都這麼忙,可等不了網頁轉菊花。

緩存分爲強緩存和協商緩存,看下流程圖

cache

緩存機制相關的字段都是在請求和響應頭上

強緩存

強緩存,在緩存有效期內,客戶端直接讀取本地資源。

強緩存返回的狀態碼是 200

Expires

http1.0 中使用,表示資源失效的具體時間點 Expires:Sat, 09 Jun 2018 08:13:56 GMT ,如果訪問器和本地時間不一致,可能就會出現問題,在如今 http1.1中換成了 max-age ,爲了兼容也能夠加上。

Cache-control

指定指令來實現緩存機制,多個指令間逗號分隔,常見的指令有如下幾個,完整的可點擊下文中的 mdn 鏈接查看

max-age: 強緩存的有效時間,單位秒 max-age=30672000

no-cache:使用緩存協商,先與服務器確認返回的響應是否被更改。

no-store:直接禁止遊覽器緩存數據,每次用戶請求該資源,都會向服務器發送一個請求,每次都會下載完整的資源,可用於關閉緩存。

public :代表響應能夠被任何對象(包括:發送請求的客戶端,代理服務器,等等)緩存,即便是一般不可緩存的內容(例如,該響應沒有max-age指令或Expires消息頭)。

private :代表響應只能被單個用戶緩存,不能做爲共享緩存(即代理服務器不能緩存它)。私有緩存能夠緩存響應內容。

強緩存

強緩存,在緩存有效期內,客戶端直接讀取本地資源。

強緩存返回的狀態碼是 200

Expires

http1.0 中使用,表示資源失效的具體時間點 Expires:Sat, 09 Jun 2018 08:13:56 GMT ,如果訪問器和本地時間不一致,可能就會出現問題,在如今 http1.1中換成了 max-age ,爲了兼容也能夠加上。

協商緩存

協商緩存,關鍵在於協商,在使用本地緩存以前,須要先跟服務器作個對比,服務器告知你的資源可用,是最新的,那就能夠直接取本地資源,反之,服務器返回最新的資源給客戶端,客戶端收到後更新本地資源。

狀態碼:

  • 若本地資源是最新的,那麼返回 304 (考點!)
  • 若比對後,須要從服務器獲取最新資源,那就是正常的 200
Last-modified If-Modified-Since

採用資源最後修改時間來判斷,單位精度秒

Last-Modified:服務器資源的最新更新時間 Tue, 14 Jan 2020 09:18:29 GMT

If-Modified-Since:客戶端發起協商,把本地記錄的文件更新時間傳給服務器,服務器進行判斷比較

這個判斷方式是 http1.0 的產物,由於時間精度是秒,若文件的更新頻率在秒級之內,就會出現文件不一致。

ETag If-None-Match

爲了解決上面的那個問題, http1.1 加了這組標記

ETag:服務器根據內容生成惟一的字符串標識

If-None-Match:客戶端發起協商,把本地記錄的 hash 標識傳給服務器,服務器進行判斷比較。

若同時存在 Last-ModifiedETag , ETag 的優先級更高。

瀏覽器緩存存放位置

browser-cache

可看到有兩個來源:

memory cache:內存中讀取

disk cache:硬盤中讀取

內存固然要比硬盤讀取快,爲啥會有存放硬盤呢?

由於內存瀏覽器內存有限啊,因此瀏覽器會有一套機制,根據文件大小何使用頻率存放不一樣的位置,具體的實現取決於瀏覽器廠商,不過這微小對用戶是無感知的。

參考文檔

developer.mozilla.org/zh-CN/docs/…

瞭解 PWA 麼

PWA(Progressive web apps,漸進式 Web 應用)運用現代的 Web API 以及傳統的漸進式加強策略來建立跨平臺 Web 應用程序。(來自 MDN)

先看看 PWA 有哪些核心技術,就知道它有哪些優點了

App Shell

App Shell 架構是構建 Progressive Web App 的一種方式,這種應用能可靠且即時地加載到您的用戶屏幕上,與本機應用類似。

這個模型包含界面所須要的最小資源文件,若是離線緩存,能夠確保重複訪問都有快速響應的特性,頁面可快速渲染,網絡僅僅獲取數據。

或者這麼理解, App Shell 就相似於原生app,沒網絡也能夠本地啓動。

ServiceWork

PWA 的核心,上面說到緩存可讓頁面儘快加載,但必須有網絡的狀況下才行,沒網絡下還想加載網頁咋辦?

ServiceWork 持久的離線緩存的能力就能夠實現。

Service Worker 有如下功能和特性:

  • 一個獨立的 worker 線程,獨立於當前網頁進程,有本身獨立的 worker context

  • 一旦被 install,就永遠存在,除非被手動 unregister

  • 用到的時候能夠直接喚醒,不用的時候自動睡眠

  • 可編程攔截代理請求和返回,緩存文件,緩存的文件能夠被網頁進程取到(包括網絡離線狀態)

  • 離線內容開發者可控

  • 能向客戶端推送消息

  • 不能直接操做 DOM

  • 必須在 HTTPS 環境下才能工做

  • 異步實現,內部大都是經過 Promise 實現

js 是單線程的,ServiceWork 獨立線程意味着不會阻塞js執行;可編程攔截代理請求和返回,可自定義文件緩存策略。

這些特色意味着開發者有足夠的權限去操做緩存,讓緩存作到優雅,效率達到極致

接下來核心是如何讓設計緩存策略,

  1. 緩存優先,先查詢緩存,若存在,直接返回,不存在,請求服務,更新緩存
  2. 服務端優先,不查詢緩存,直接請求服務端,服務端失敗纔會查詢緩存
  3. 穩定優先,先查詢緩存,有就讀取,同時請求服務端更新資源

推薦你們看看開源的 wordbox 封裝的緩存策略,策略更加豐富。

代碼不復雜,主要是聲明週期、與js線程間通訊、api調用,就不貼上來了。

參考文檔:

lavas.baidu.com/pwa/offline…

developer.mozilla.org/zh-CN/docs/…

URL 輸入到渲染的過程

  1. 域名解析,找到服務地址
  2. 構建 TCP 鏈接,如有 https,則多一層 TLS 握手,
  3. 特殊響應碼處理 301 302
  4. 解析文檔
  5. 構建 dom 樹和 csscom
  6. 生成渲染樹:從DOM樹的根節點開始遍歷每一個可見節點,對於每一個可見的節點,找到CSSOM樹中對應的規則,並應用它們,根據每一個可見節點以及其對應的樣式,組合生成渲染樹
  7. Layout(迴流):根據生成的渲染樹,進行迴流(Layout),獲得節點的集合信息
  8. Painting(重繪):根據渲染樹及其迴流獲得的集合信息,獲得節點的絕對像素。
  9. 繪製,在頁面上展現,這一步還涉及到繪製層級、GPU相關的知識點
  10. 加載js腳本,加載完成解析js腳本

這是一個大體的流程,面試官會從中挑出其餘點來接着問

重繪和迴流(重排)

先看這圖,html文檔 和 css 渲染過程的圖

layout

頁面是採用流式佈局來繪製,左到右,上到下,那麼一個節點的空間屬性如果發生了變化,那麼會影響到其餘節點的空間佈局,須要從新收集節點信息,在進行繪製,這就是迴流的過程。

重繪指的是對元素的外觀作處理,好比顏色、背景、陰影等。

因此迴流必定觸發重繪。

觸發迴流的場景

獲取位置信息或者修改幾何屬性,以下:

  • 添加或刪除可見的DOM元素
  • 元素的位置發生變化
  • 元素的尺寸發生變化(包括外邊距、內邊框、邊框大小、高度和寬度等)
  • 內容發生變化,好比文本變化或圖片被另外一個不一樣尺寸的圖片所替代。
  • 頁面一開始渲染的時候(這確定避免不了)
  • 瀏覽器的窗口尺寸變化(由於迴流是根據視口的大小來計算元素的位置和大小的)
  • 獲取位置信息,由於須要迴流計算最新的值
// 獲取位置信息相關屬性
- offsetTop offsetLeft offsetWidth offsetHeight 相對於父級容器的偏移量
- scrollTop scrollLeft scrollWidth scrollHeight 相對於父級容器滾動上去的距離
- clientTop clientLeft clientWidth clientHeight 元素邊框的厚度
- getComputedStyle()
- getBoundingClientRect
複製代碼

迴流的優化

對樹的局部甚至全局從新生成是很是耗性能的,因此要避免頻繁觸發迴流

  • 現代瀏覽器已經幫咱們作了優化,採用隊列存儲屢次的迴流操做,而後批量執行,但獲取佈局信息例外,由於要獲取到實時的數值,瀏覽器就必需要清空隊列,當即執行迴流。
  • 編碼上,避免連續屢次修改,可經過合併修改,一次觸發
  • 對於大量不一樣的 dom 修改,能夠先將其脫離文檔流,好比使用絕對定位,或者 display:none ,在文檔流外修改完成後再放回文檔裏中
  • 經過節流和防抖控制觸發頻率
  • css3 硬件加速,transform、opacity、filters,開啓後,會新建渲染層

開啓GPU加速的方法

開啓後,會將 dom 元素提高爲獨立的渲染層,它的變化不會再影響文檔流中的佈局。

  • transform: translateZ(0)
  • opacity
  • filters
  • Will-change

說下對 http 協議的瞭解

http 是創建在 TCP 上的應用層協議,超文本傳送協議。

是單向的短連接,目前有 http1.0 http 1.1 http2.0

http1.0 :客戶端的每次請求都要求創建一次單獨的鏈接,在處理完本次請求後,就自動釋放鏈接。 http1.1 :能夠在一次鏈接中處理多個請求,而且多個請求能夠重疊進行,不須要等待一個請求結束後再發送下一個請求 http2.0 :可支持多路複用,一個 tcp 可同時傳輸多個 http 請求,頭部數據還作了壓縮

面試官問這個通常是更關注對 tcp 的理解

tcp

tcp 是傳輸層協議,它的特色是:三次握手和四次揮手。

三次握手的目的是爲了防止已經失效的鏈接請求報文段忽然又傳到服務端,而產生錯誤,因此要創建可靠的鏈接發送數據

三次握手創建鏈接過程:

  1. 客戶端發送位碼爲syn=1,隨機產生數據包到服務器,服務器由SYN=1知道客戶端要求創建聯機(客戶端:我要鏈接你)
  2. 服務器收到請求後要確認聯機信息,向A發送ack number=(客戶端的seq+1),syn=1,ack=1,隨機生成數據包(服務器:好的,你來連吧)
  3. 客戶端收到後檢查ack number是否正確,即第一次發送的seq number+1,以及位碼ack是否爲1,若正確,客戶端會再發送ack number=(服務器的seq+1),ack=1,服務器收到後確認seq值與ack=1則鏈接創建成功。(客戶端:好的,我來了)

四次揮手斷開鏈接的過程:

  1. 客戶端發送請求給服務端,申請主動斷開鏈接,進入等待狀態,不在往服務端發送數據,可是接收數據(客戶端:我要斷開鏈接了)
  2. 服務端收到後,告知客戶端知道了,服務端進行等待狀態,不在接收數據,可是能夠繼續發送數據(服務端:好,我知道了,可是要等一等)
  3. 客戶端收到服務端的告知後,進入下一階段的等待。(客戶端:好,我等)
  4. 服務端完成剩餘數據的發送後,告知客戶端能夠斷開了,服務端不接收和讀取數據(服務端:你能夠斷開了)
  5. 客戶端收到後,告知服務端,已收到,而後釋放連接(客戶端:好的,我斷開連接了)
  6. 服務端收到後,也釋放連接

UDP

傳輸層的另一個協議 UDP 稱爲用戶數據報協議,無鏈接的傳輸協議。

UDP 是報文的搬運工,不須要創建徹底可靠的連接,不保證數據的可靠性,由於協議控制項比較少,且報文頭部簡單,報文體積相對要小,速度上相比更快,實時性更高,好比電話會議、多媒體數據流等場景就採用 UDP

介紹下 https

http 報文傳輸過程當中是明文的,能夠經過抓包的方式看到報文內容,這就暴露一個安全問題,易被劫持篡改。

爲了解決這個問題,就有了 TLS ,https = http + TLS

TLS:安全傳輸層協議,用於在兩個通訊應用程序之間提供保密性和數據完整性,該協議由兩層組成: TLS 記錄協議(TLS Record)和 TLS 握手協議(TLS Handshake)。

TLS 利用非對稱加密演算來對通訊方作身份認證,以後交換對稱密鑰做爲會談密鑰(Session key),所以 https 分爲兩個階段

  1. 經過非對稱加解密確認對方身份是否合法,若合法生成會話密鑰。(這一步是核心)
  2. 報文的在發送前,先用會話密鑰進行對稱加密,在傳輸。

TLS 握手

步驟以下:

  1. 客戶端請求服務端創建SSL連接,服務端並向客戶端發送一個隨機數 randomC 和 CA 機構頒發的證書(注:CA相關下面詳細介紹)
  2. 客戶端對證書進行驗證,驗證經過後,生成一個隨機數 randomS ,用公鑰對 randomS 加密 ,同時用 randomS 生成一段簽名,發送給服務端
  3. 服務端接收到後,用私鑰對祕文解密,用解密後的 key 生成簽名,並與客戶端傳來的簽名進行比較,檢驗經過後,而後生成一個隨機數 randomP ,並用私鑰加密,還有隨機數生成的 hash 值,一併發給客戶端。
  4. 客戶端用公鑰解密,並校驗 hash 值經過後,兩端利用 randomC randomS randomP 經過必定的算法生成 session key,後續的報文將經過 session key 對稱加密進行傳輸。

對前端來講,畢竟偏向於理論,因此建議你們根據步驟畫一畫流程圖,更利於理解記憶。

CA 證書

上面第一步講到 CA證書,假如沒有證書驗證這一環節,那麼公鑰在傳輸過程極有可能被中間人攔截,來個狸貓換太子,將服務端的公鑰換成它本身的公鑰,返回給客戶端,這麼一來,就徹底起不到加密的做用了,也就是中間人攻擊。

因此就須要一個驗證的機制,保證公鑰是來自服務端的,沒有被篡改的,CA證書就出場了。

CA證書,是由 CA 機構頒發的一個憑證,裏面關鍵的信息有,簽名算法、簽名hash算法、頒發者、有效期、公鑰、指紋,這個兩個算法就表示對稱階段和非對稱階段採用的算法,公鑰就是服務端的公鑰,在申請的時候,企業須要上傳公鑰給CA機構,重點是這個指紋,這個指紋是由 CA 機構經過私鑰對一段簽名加密生成的。

因此經過驗證證書是否合法,就知道公鑰是否被篡改,那麼怎麼驗證合法呢?

天然是經過證書的指紋。

在瀏覽器和我的PC中,都預裝了頂級的 CA 機構證書和公鑰,因此瀏覽器獲取到證書後,經過內置的公鑰對指紋進行解密獲得簽名,而後瀏覽器也根據一樣的規則生成一段簽名,兩段簽名進行比較,驗證經過,那麼這個證書中公鑰就是可信的。

那麼這樣一來是否是就能夠徹底避免了中間人攻擊呢?

畢竟頂級的 CA 證書是內置的,仍是有一種方式,你們是否還記得咱們用,咱們是能夠用 Fiddle 對 https 進行抓包的,那 Fiddle 算不算中間人呢 ?

Fiddle 之因此能攔截成功是由於,咱們在抓包以前,在咱們本身手機安裝一份來自 Fiddle 的證書,也就是客戶端本身信任了第三方來源的證書,這麼一來客戶端天然能解析出 Fiddle 轉發出來的報文啦。

因此只要不隨意信任第三方證書,基本上是不會發生中間人攻擊的。

什麼狀況會觸發 options 請求

options 一般用於,在跨域請求前發起預檢請求,以檢測請求是否被服務器接受。

跨域請求中分爲簡單請求和預檢請求兩種,符合如下條件可視爲簡單請求:

  • 使用的 HTTP method 是 GET POST HEAD
  • content-type 是 text/plain mutipart/form-data application/x-www-form-urlencode 三種之一
  • 請求頭只能包含這些
- Accept
- Accept-Language
- Content-Language
- Content-Type (須要注意額外的限制)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
複製代碼

除去簡單請求外,其餘請求就會先觸發預檢請求。

常見的,好比使用

  • content-Type 爲 application/xml 或 text/xml 的 POST 請求
  • 設置自定義頭,好比 X-JSON、X-MENGXIANHUI 等

預檢請求返回的頭部報文中有

Access-Control-Allow-Origin: 服務器可接受的請求來源

Access-Control-Request-Method: 服務器實際請求所使用的 HTTP 方法

Access-Control-Request-Headers: 服務器實際請求所攜帶的自定義首部字段。

客戶端基於從預檢請求得到的信息來判斷,是否繼續執行跨域請求。

注意:跨域請求若想發送 cookie 信息,須要服務端設置 resp.setHeader("Access-Control-Allow-Credentials","true"); 客戶端設置 withCredentials: true

參考資料: cloud.tencent.com/developer/n…

http有哪些常見請求頭

直接看圖

rquest-head

response-head

報文提交 Content-Type 的幾種區別

Content-Type 字段來獲知請求中的消息主體是用何種方式編碼

Content-Type: application/json : json 字符串 Content-Type: application/x-www-form-urlencoded : & 將 key=value 進行拼接, jquery 默認使用這個 Content-Type: multipart/form-data : 經常使用於文件上傳

關於前端安全防範

主要有兩類 XSS CSRF

XSS

跨站腳本攻擊,攻擊者將一段可執行的代碼注入到網頁中,如連接、輸入框,分爲持久形和臨時性的,持久性的是惡意代碼被存儲到數據庫裏,會形成持久的攻擊;臨時性的是僅在當前被工具頁面上生效;

防範的方式是對與網頁上獲取的內容要作轉義處理。

CSRF

跨站請求僞造,構造一個釣魚網站,利用站點對瀏覽器的信任,從而欺騙用戶,發起請求進行惡意操做。

用戶在瀏覽器登陸後,站點是信任瀏覽器的,但瀏覽器是無法知道請求是不是用戶自願發起的,站點信任後,所發起的請求瀏覽器都是信任的。

那麼用戶是已登陸的狀況下,釣魚站點中發起跨域請求,跨域標籤或者 form 表單,就會把用戶的認證信息 cookies 帶上,從而到達僞造用戶身份進行攻擊。

防範方式:

  1. 服務端校驗 Referer ,但某些瀏覽器可能能夠修改 Referer
  2. 隨機 token ,每訪問頁面就生成一個 token ,頁面中的請求把這個 token 帶上,服務端對 token 進行校驗。注意這個 token 不能存儲在 cookie 中

關於 xss csrf 網上有很詳細的介紹,不過核心原理仍是比較簡單的。

瞭解 CORB

第一次聽到有點懵,由於是 CORS ,回來查了資料才明白。

CORB 是一種判斷是否要在跨站資源數據到達頁面以前阻斷其到達當前站點進程中的算法,下降了敏感數據暴露的風險。是站點隔離的一種實現機制,針對跨域標籤,保護站點資源。

當跨域請求回來的數據 MIME type 同跨域標籤應有的 MIME 類型不匹配時,瀏覽器會啓動 CORB 保護數據不被泄漏,被保護的數據類型只有 html xml json

MIME type

MIME 是一個互聯網標準,擴展了電子郵件標準,使其能夠支持更多的消息類型。常見 MIME 類型如:text/html text/plain image/png application/javascript ,用於標識返回消息屬於哪種文檔類型。寫法爲 type/subtype。 在 HTTP 請求的響應頭中,以 Content-Type: application/javascript; charset=UTF-8 的形式出現,MIME type 是 Content-Type 值的一部分

這篇文章寫的很是詳細,建議你們直接查看 Cross-Origin Read Blocking (CORB)

跨域的解決方案

主流的有一下幾種

利用跨域標籤 image script 發起 get 方法的跨域請求

  1. image 標籤實現
var img = new Image;
img.onload = function() {
},
img.onerror = function() {
},
img.src = options.url;
複製代碼
  1. script 標籤實現 這個就是常說的 JSONP 。script 會執行返回的字符串,那麼能夠經過約定一個參數,前端的參數指定一個全局的方法,服務端獲取到全局方法後,構造一個執行函數的字符串,並把報文放入函數的參數中。瀏覽器接收到後以 application/javascript 的方式進行解析,就能夠觸發預設好的回調函數。
/* html */
let scr = document.createElement('script');
scr.src = `http://127.0.0.1:3500/xx?callback=cb`
document.getElementsByTagName('head')[0].appendChild(scr)
function cb(res){
    console.log('into');
    console.log(res);
}

/* server */ 
let data = { name: 'xiaoli' }
var str = ctx.query.callback + '(' + JSON.stringify(data) + ')';
// ctx.query = {callback:'cb'}
// str = 'cb({"name":"xiaoli"})'
ctx.body = str;
複製代碼

反向代理

經常使用 nginx 作反向代理,詳細配置就很少說了

CORS

這就全是服務端的工做了,主要的三個參數

Access-Control-Allow-Origin: 服務器可接受的請求來源

Access-Control-Request-Method: 服務器實際請求所使用的 HTTP 方法

Access-Control-Request-Headers: 服務器實際請求所攜帶的自定義首部字段。

中間層 BFF 作轉換

假若有 BFF 層的話,能夠在這一層作一箇中轉,這個就得看項目架構是否有條件了。

html的meta裏設置緩存和http請求頭設置緩存有什麼區別嗎

html 的 meta 設置的緩存策略是對於當前文檔有效,用於定義頁面緩存。

與http的請求參數很相像,就不重複了,詳細介紹可參考 設置meta標籤 清除頁面緩存

history 路由和 hash 路由

hash 路由

hash 路由,在 html5 前,爲了解決單頁路由跳轉問題採用的方案, hash 的變化不會觸發頁面渲染,服務端也沒法獲取到 hash 值,前端可經過監聽 hashchange 事件來處理hash值的變化

window.addEventListener('hashchange', function(){ 
    // 監聽hash變化,點擊瀏覽器的前進後退會觸發
})
複製代碼

history 路由

history 路由,是 html5 的規範,提供了對history棧中內容的操做,經常使用api有:

window.history.pushState(state, title, url) 
// let currentState = history.state; 獲取當前state
// state:須要保存的數據,這個數據在觸發popstate事件時,能夠在event.state裏獲取
// title:標題,基本沒用,通常傳 null
// url:設定新的歷史記錄的 url。新的 url 與當前 url 的 origin 必須是一樣的,不然會拋出錯誤。url能夠是絕對路徑,也能夠是相對路徑。
//如 當前url是 https://www.baidu.com/a/,執行history.pushState(null, null, './qq/'),則變成 https://www.baidu.com/a/qq/,
//執行history.pushState(null, null, '/qq/'),則變成 https://www.baidu.com/qq/

window.history.replaceState(state, title, url)
// 與 pushState 基本相同,但她是修改當前歷史記錄,而 pushState 是建立新的歷史記錄

window.addEventListener("popstate", function() {
    // 監聽瀏覽器前進後退事件,pushState 與 replaceState 方法不會觸發 
});
複製代碼

js 事件的幾種綁定方式

  • 在 dom 元素中直接綁定,<div class="an" onclick="aa()">aaaa</div>
  • js 中綁定 document.getElementById("demo").οnclick=function(){}
  • 添加監聽事件 document.addEventListener('name',()=>{})

什麼是事件委託

瀏覽器中的事件觸發有三個階段:

  1. 最從外層開始往裏傳播,即事件捕獲階段
  2. 事件抵達了目標節點,即目標階段
  3. 從目標階段往外層返回,即冒泡階段

事件委託也叫事件代理,在 dom 節點中,由於有事件冒泡機制,因此子節點的事件能夠被父節點捕獲。

所以,在適當的場景下將子節點的事件用父節點監聽處理,支持的事件 點擊事件 鼠標事件監聽。

事件代理的優點:

  1. 能夠減小監聽器的數量,減小內存佔用
  2. 對於動態新增的子節點,能夠實現事件監聽

關於事件捕獲和事件冒泡的理解:

事件捕獲:事件從外往裏傳播,addEventListener 最後一個參數設置成 true 就能夠捕獲事件,默認是 false ,監聽事件冒泡。捕獲是計算機處理輸入的邏輯

事件冒泡:事件由內往外傳播,冒泡是人類理解事件的思惟。

target與currentTarget區別

target:指的是事件流的目標階段,獲取的是被點擊的元素。

currentTarget:在事件流的捕獲和冒泡階段時,是指向當前事件活動對象,只有在目標階段的時候,二者纔會相等

CSS加載問題

根據頁面渲染流程可得知:

  1. css加載不會阻塞DOM樹的解析;
  2. css加載會阻塞DOM樹的渲染;
  3. css加載會阻塞後面js語句的執行

介紹下資源預加載 prefetch/preload async/defer

prefetch preload

都是告知瀏覽器提早加載文件(圖片、視頻、js、css等),但執行上是有區別的。

prefetch :其利用瀏覽器空閒時間來下載或預取用戶在不久的未來可能訪問的文檔。<link href="/js/xx.js" rel="prefetch">

preload : 能夠指明哪些資源是在頁面加載完成後即刻須要的,瀏覽器在主渲染機制介入前就進行預加載,這一機制使得資源能夠更早的獲得加載並可用,且更不易阻塞頁面的初步渲染,進而提高性能。 <link href="/js/xxx.js" rel="preload" as="script"> 須要 as 指定資源類型,目前可用的屬性類型有以下:

audio: 音頻文件。
document: 一個將要被嵌入到<frame>或<iframe>內部的HTML文檔。
embed: 一個將要被嵌入到<embed>元素內部的資源。
fetch: 那些將要經過fetch和XHR請求來獲取的資源,好比一個ArrayBuffer或JSON文件。
font: 字體文件。
image: 圖片文件。
object: 一個將會被嵌入到<embed>元素內的文件。
script: JavaScript文件。
style: 樣式表。
track: WebVTT文件。
worker: 一個JavaScript的web worker或shared worker。
video: 視頻文件。
複製代碼

js async 和 defer 的區別

用於js腳本預加載

async : 加載腳本和渲染後續文檔元素並行進行,腳本加載完成後,暫停html解析,當即解析js腳本

defer : 加載腳本和渲染後續文檔元素並行進行,但腳本的執行會等到 html 解析完成後執行

js-async-defer.png

參考資料:

developer.mozilla.org/zh-CN/docs/…

developer.mozilla.org/zh-CN/docs/…

介紹下 viewport

<meta name="viewport" content="width=500, initial-scale=1">

這裏只指定了兩個屬性,寬度和縮放,實際上 viewport 能控制的更多,它能表示的所有屬性以下:

  • width:頁面寬度,能夠取值具體的數字,也能夠是 device-width,表示跟設備寬度相等。
  • height:頁面高度,能夠取值具體的數字,也能夠是 device-height,表示跟設備高度相等。
  • initial-scale:初始縮放比例。
  • minimum-scale:最小縮放比例。
  • maximum-scale:最大縮放比例。
  • user-scalable:是否容許用戶縮放。

移動端300ms延時的緣由? 如何處理?

由於在之前移動端雙擊能夠縮放或者滑動,因此爲了區分是點擊仍是雙擊,加了 300ms 的延遲。

解決方案:

  • css touch-action touch-action的默爲 auto,將其置爲 none 便可移除目標元素的 300 毫秒延遲 缺點: 新屬性,可能存在瀏覽器兼容問題
  • 利用touchstart和touchend來模擬click事件,缺點有點擊穿透
  • fastclick 原理: 在檢測到touchend事件的時候,會經過DOM自定義事件當即出發模擬一個click事件,並把瀏覽器在300ms以後真正的click事件阻止掉
  • 全部版本的Android Chrome瀏覽器,若是設置viewport meta的值有user-scalable=no,瀏覽器也是會立刻出發點擊事件。

Web Worker

(後續再補上)

瀏覽器性能監控

使用 performance.timing 這個api就能夠獲取到絕大部分性能相關的數據

performance

  • navigationStart :在同一個瀏覽器上下文中,前一個網頁(與當前頁面不必定同域)unload 的時間戳,若是無前一個網頁 unload ,則與 fetchStart 值相等
  • unloadEventStart :前一個網頁(與當前頁面同域)unload 的時間戳,若是無前一個網頁 unload 或者前一個網頁與當前頁面不一樣域,則值爲 0
  • redirectStart :第一個 HTTP 重定向發生時的時間。有跳轉且是同域名內的重定向纔算,不然值爲 0
  • redirectEnd :最後一個 HTTP 重定向完成時的時間。有跳轉且是同域名內的重定向纔算,不然值爲 0

開始加載當前頁面

  • fetchStart :瀏覽器準備好使用 HTTP 請求抓取文檔的時間,這發生在檢查本地緩存以前

網絡傳輸階段 DNS TCP

  • domainLookupStart :DNS 域名查詢開始的時間,若是使用了本地緩存(即無 DNS 查詢)或持久鏈接,則與 fetchStart 值相等
  • domainLookupEnd :DNS 域名查詢完成的時間,若是使用了本地緩存(即無 DNS 查詢)或持久鏈接,則與 fetchStart 值相等
  • connectStart :HTTP(TCP) 開始創建鏈接的時間,若是是持久鏈接,則與 fetchStart 值相等,若是在傳輸層發生了錯誤且從新創建鏈接,則這裏顯示的是新創建的鏈接開始的時間
  • secureConnectionStart :HTTPS 鏈接開始的時間,若是不是安全鏈接,則值爲 0
  • connectEnd :HTTP(TCP) 完成創建鏈接的時間(完成握手),若是是持久鏈接,則與 fetchStart 值相等,若是在傳輸層發生了錯誤且從新創建鏈接,則這裏顯示的是新創建的鏈接完成的時間

讀取文檔階段

  • requestStart :HTTP 請求讀取真實文檔開始的時間(完成創建鏈接),包括從本地讀取緩存,鏈接錯誤重連時,這裏顯示的也是新創建鏈接的時間
  • responseStart :HTTP 開始接收響應的時間(獲取到第一個字節),包括從本地讀取緩存
  • responseEnd :HTTP 響應所有接收完成的時間(獲取到最後一個字節),包括從本地讀取緩存

解析文檔階段

  • domLoading :開始解析渲染 DOM 樹的時間,此時 Document.readyState 變爲 loading,並將拋出 readystatechange 相關事件
  • domInteractive :完成解析 DOM 樹的時間,Document.readyState 變爲 interactive,並將拋出 readystatechange 相關事件
  • domContentLoadedEventStart :DOM 解析完成後,網頁內資源加載開始的時間,表明DOMContentLoaded事件觸發的時間節點
  • domContentLoadedEventEnd :DOM 解析完成後,網頁內資源加載完成的時間(如 JS 腳本加載執行完畢),文檔的DOMContentLoaded 事件的結束時間,也就是jQuery中的domready時間;
  • domComplete :DOM 樹解析完成,且資源也準備就緒的時間,Document.readyState 變爲 complete,並將拋出 readystatechange 相關事件
  • loadEventStart :load 事件發送給文檔,也即 load 回調函數開始執行的時間,若是沒有綁定 load 事件,值爲 0
  • loadEventEnd :load 事件的回調函數執行完畢的時間,若是沒有綁定 load 事件,值爲 0

各個階段時間段查詢

DNS查詢耗時 = domainLookupEnd - domainLookupStart

TCP連接耗時 = connectEnd - connectStart

request請求耗時 = responseEnd - responseStart

解析dom樹耗時 = domComplete - domInteractive

白屏時間 = domloadng - fetchStart

domready時間 = domContentLoadedEventEnd - fetchStart

onload時間 = loadEventEnd - fetchStart

舉幾個h5的新特性

這個題有點無聊了,但仍是遇到了

  • 新增語義化標籤
  • 新增api、本地存儲
  • css 邊框、背景、動畫

對於連續的中文輸入有哪些事件

輸入框對於輸入連續中文的時候可使用如下兩個監聽事件(第一次知道還有這個事件):

compositionstart:事件觸發於一段文字的輸入以前(相似於 keydown 事件,可是該事件僅在若干可見字符的輸入以前,而這些可見字符的輸入可能須要一連串的鍵盤操做、語音識別或者點擊輸入法的備選詞)。

compositionend:當文本段落的組成完成或取消時,事件將被觸發 (具備特殊字符的觸發, 須要一系列鍵和其餘輸入, 如語音識別或移動中的字詞建議)。

相關文章
相關標籤/搜索