前端試題及答案

來自javascript

HTML

DOCTYPE 的做用是什麼?

DOCTYPE通常位於文檔的第一行,它告訴瀏覽器以什麼樣的格式來解析文檔,通常指定了以後會以標準模式來進行文檔解析,不然就以兼容模式進行解析。在標準模式下,瀏覽器的解析規則都是按照最新的標準進行解析的。而在兼容模式下,瀏覽器會以向後兼容的方式來模擬老式瀏覽器的行爲,以保證一些老的網站的正確訪問。

在 html5 以後再也不須要指定 DTD 文檔,由於 html5 之前的 html 文檔都是基於 SGML 的,因此須要經過指定 DTD 來定義文檔中容許的屬性以及一些規則。而 html5 再也不基於 SGML 了,因此再也不須要使用 DTD。css

在HTML中,文檔類型聲明是必要的。全部的文檔的頭部,你都將會看到" <!DOCTYPE html>" 的身影。這個聲明的目的是防止瀏覽器在渲染文檔時,切換到咱們稱爲「 怪異模式(兼容模式)」的渲染模式。「 <!DOCTYPE html>" 確保瀏覽器按照最佳的相關規範進行渲染,而不是使用一個不符合規範的渲染模式。——MDN解釋

標準模式和兼容模式有什麼區別?

標準模式的渲染方式和JS引擎的解析方式都是以該瀏覽器支持的的最高標準運行。兼容模式中,頁面以寬鬆向後兼容的方式顯示,模擬老式瀏覽器的行爲以防止站點沒法工做。html

行內元素和塊級元素以及他們的區別

一個行內元素只佔據它對應標籤的邊框所包含的空間。

常見的行內元素有 a b span img strong sub sup button input label select textarea前端

塊級元素佔據其父元素(容器)的整個寬度,所以建立了一個「塊」。

常見的塊級元素有 div ul ol li dl dt dd h1 h2 h3 h4 h5 h6 p
區別vue

(1) 格式上,默認狀況下,行內元素不會以新行開始,而塊級元素會新起一行。
(2) 內容上,默認狀況下,行內元素只能包含文本和其餘行內元素。而塊級元素能夠包含行內元素和其餘塊級元素。
(3) 行內元素與塊級元素屬性的不一樣,主要是盒模型屬性上:行內元素設置 width 無效,height 無效(能夠設置 line-height),設置 margin 和 padding 的上下不會對其餘元素產生影響。

HTML5 元素的分類

HTML4中,元素被分紅兩大類: inline(內聯元素)與 block(塊級元素)。但在實際的開發過程當中,由於頁面表現的須要,前端工程師常常把 inline 元素的 display 值設定爲 block (好比 a 標籤),也常常把 block 元素的 display 值設定爲 inline 以後更是出現了 inline-block 這一對外呈現 inline 對內呈現 block 的屬性。所以,簡單地把 HTML 元素劃分爲 inline 與 block 已經再也不符合實際需求。

HTML5中,元素主要分爲7類:Metadata Flow Sectioning Heading Phrasing Embedded Interactivehtml5

空元素定義

標籤內沒有內容的 HTML 標籤被稱爲空元素。空元素是在開始標籤中關閉的。

常見的空元素有:br hr img input link metajava

link 標籤訂義

link 標籤訂義文檔與外部資源的關係。

link 元素是空元素,它僅包含屬性。 此元素只能存在於 head 部分,不過它可出現任何次數。react

link 標籤中的 rel 屬性定義了當前文檔與被連接文檔之間的關係。常見的 stylesheet 指的是定義一個外部加載的樣式表。css3

頁面導入樣式時,使用 link 和 @import 有什麼區別?

(1)從屬關係區別。 @import 是 CSS 提供的語法規則,只有導入樣式表的做用;link 是 HTML 提供的標籤,不只能夠加載 CSS 文件,還能夠定義 RSS、rel 鏈接屬性、引入網站圖標等。

(2)加載順序區別。加載頁面時,link 標籤引入的 CSS 被同時加載;@import 引入的 CSS 將在頁面加載完畢後被加載。git

(3)兼容性區別。@import 是 CSS2.1 纔有的語法,故只可在 IE5+ 才能識別;link 標籤做爲 HTML 元素,不存在兼容性問題。

(4)DOM 可控性區別。能夠經過 JS 操做 DOM ,插入 link 標籤來改變樣式;因爲 DOM 方法是基於文檔的,沒法使用 @import 的方式插入樣式。

你對瀏覽器的理解

瀏覽器的主要功能是將用戶選擇的 web 資源呈現出來,它須要從服務器請求資源,並將其顯示在瀏覽器窗口中,資源的格式一般是 HTML,也包括 PDF、image 及其餘格式。用戶用 URI(Uniform Resource Identifier 統一資源標識符)來指定所請求資源的位置。

URI(統一資源標識符)是一個指向資源的字符串。最一般用在 URL上來指定Web上資源文件的具體位置。相比之下,URN是在給定的命名空間用名字指向具體的資源,如:書本的ISBN。
HTML 和 CSS 規範中規定了瀏覽器解釋 html 文檔的方式,由 W3C 組織對這些規範進行維護,W3C 是負責制定 web 標準的
組織。

可是瀏覽器廠商紛紛開發本身的擴展,對規範的遵循並不完善,這爲 web 開發者帶來了嚴重的兼容性問題。

簡單來講瀏覽器能夠分爲兩部分,shell 和 內核。

其中 shell 的種類相對比較多,內核則比較少。shell 是指瀏覽器的外殼:例如菜單,工具欄等。主要是提供給用戶界面操做,參數設置等等。它是調用內核來實現各類功能的。內核纔是瀏覽器的核心。內核是基於標記語言顯示內容的程序或模塊。

介紹一下你對瀏覽器內核的理解?

主要分紅兩部分:渲染引擎和 JS 引擎。
渲染引擎的職責就是渲染,即在瀏覽器窗口中顯示所請求的內容。默認狀況下,渲染引擎能夠顯示 html、xml 文檔及圖片,它也能夠藉助插件(一種瀏覽器擴展)顯示其餘類型數據,例如使用 PDF 閱讀器插件,能夠顯示 PDF 格式。
JS 引擎:解析和執行 javascript 來實現網頁的動態效果。

最開始渲染引擎和 JS 引擎並無區分的很明確,後來 JS 引擎愈來愈獨立,內核就傾向於只指渲染引擎。

瀏覽器的渲染原理?

(1)首先解析收到的文檔,根據文檔定義構建一棵 DOM 樹,DOM 樹是由 DOM 元素及屬性節點組成的。
(2)而後對 CSS 進行解析,生成 CSSOM 規則樹。
(3)根據 DOM 樹和 CSSOM 規則樹構建渲染樹。渲染樹的節點被稱爲渲染對象,渲染對象是一個包含有顏色和大小等屬性的矩形,渲染對象和 DOM 元素相對應,但這種對應關係不是一對一的,不可見的 DOM 元素不會被插入渲染樹。還有一些 DOM 元素對應幾個可見對象,它們通常是一些具備複雜結構的元素,沒法用一個矩形來描述。
(4)當渲染對象被建立並添加到樹中,它們並無位置和大小,因此當瀏覽器生成渲染樹之後,就會根據渲染樹來進行佈局(也能夠叫作 迴流)。這一階段瀏覽器要作的事情是要弄清楚各個節點在頁面中的確切位置和大小。一般這一行爲也被稱爲「自動重排」。
(5)佈局階段結束後是繪製階段,遍歷渲染樹並調用渲染對象的 paint 方法將它們的內容顯示在屏幕上,繪製使用 UI 基礎組件。

值得注意的是,這個過程是逐步完成的,爲了更好的用戶體驗,渲染引擎將會盡量早的將內容呈現到屏幕上,並不會等到全部的html 都解析完成以後再去構建和佈局 render 樹。它是解析完一部份內容就顯示一部份內容,同時,可能還在經過網絡下載其他內容。

渲染過程當中遇到 JS 文件怎麼處理?(瀏覽器解析過程)

JavaScript 的加載、解析與執行會阻塞文檔的解析,也就是說,在構建 DOM 時,HTML 解析器若遇到了 JavaScript,那麼它會暫停文檔的解析,將控制權移交給 JavaScript 引擎,等 JavaScript 引擎運行完畢,瀏覽器再從中斷的地方恢復繼續解析文檔。

也就是說,若是你想首屏渲染的越快,就越不該該在首屏就加載 JS 文件,這也是都建議將 script 標籤放在 body 標籤底部的緣由。固然在當下,並非說 script 標籤必須放在底部,由於你能夠給 script 標籤添加 defer 或者 async 屬性。

async 和 defer 的做用是什麼?有什麼區別?(瀏覽器解析過程)

(1)腳本沒有 defer 或 async,瀏覽器會當即加載並執行指定的腳本,也就是說不等待後續載入的文檔元素,讀到就加載並執行。
(2)defer(推遲) 屬性表示延遲執行引入的 JavaScript,即這段 JavaScript 加載時 HTML 並未中止解析,這兩個過程是並行的。當整個 document 解析完畢後再執行腳本文件,在 DOMContentLoaded 事件觸發以前完成。多個腳本按順序執行。
(3)async 屬性表示異步執行引入的 JavaScript,與 defer 的區別在於,若是已經加載好,就會開始執行,也就是說它的執行仍然會阻塞文檔的解析,只是它的加載過程不會阻塞。多個腳本的執行順序沒法保證。

什麼是文檔的預解析?(瀏覽器解析過程)

Webkit和Firefox都作了這個優化,當執行JavaScript腳本時,另外一個線程解析剩下的文檔,並加載後面須要經過網絡加載的資源。這種方式可使資源並行加載從而使總體速度更快。須要注意的是,預解析並不改變DOM樹,它將這個工做留給主解析過程,本身只解析外部資源的引用,好比外部腳本、樣式表及圖片。

CSS如何阻塞文檔解析?(瀏覽器解析過程)

理論上,既然樣式表不改變 DOM 樹,也就沒有必要停下文檔的解析等待它們,然而,存在一個問題,JavaScript 腳本執行時可能在文檔的解析過程當中請求樣式信息,若是樣式尚未加載和解析,腳本將獲得錯誤的值,顯然這將會致使不少問題。

若是瀏覽器還沒有完成 CSSOM 的下載和構建,而咱們卻想在此時運行腳本,那麼瀏覽器將延遲 JavaScript 腳本執行和文檔的解析,直至其完成 CSSOM 的下載和構建。也就是說,在這種狀況下,瀏覽器會先下載和構建 CSSOM,而後再執行 JavaScript,最後再繼續文檔的解析。

渲染頁面時常見哪些不良現象?(瀏覽器渲染過程)

FOUC:
主要指的是樣式閃爍的問題,因爲瀏覽器渲染機制(好比Firefox),在CSS加載以前,先呈現了HTML,就會致使展現出現無樣式內容,而後樣式忽然呈現的現象。會出現這個問題的緣由主要是CSS加載時間過長,或者CSS被放在了文檔底部。

白屏:
有些瀏覽器渲染機制(好比chrome)要先構建 DOM 樹和CSSOM 樹,構建完成後再進行渲染,若是 CSS 部分放在 HTML 尾部,因爲CSS 未加載完成,瀏覽器遲遲未渲染,從而致使白屏;也多是把 js文件放在頭部,腳本的加載會阻塞後面文檔內容的解析,從而頁面遲遲未渲染出來,出現白屏問題。

如何優化關鍵渲染路徑?(瀏覽器渲染過程)

爲儘快完成首次渲染,咱們須要最大限度減少如下三種可變因素:
(1)關鍵資源的數量。
(2)關鍵路徑長度。
(3)關鍵字節的數量。

關鍵資源是可能阻止網頁首次渲染的資源。這些資源越少,瀏覽器的工做量就越小,對 CPU 以及其餘資源的佔用也就越少。
一樣,關鍵路徑長度受全部關鍵資源與其字節大小之間依賴關係圖的影響:某些資源只能在上一資源處理完畢以後才能開始下載,而且資源越大,下載所需的往返次數就越多。
最後,瀏覽器須要下載的關鍵字節越少,處理內容並讓其出如今屏幕上的速度就越快。要減小字節數,咱們能夠減小資源數(將它們刪除或設爲非關鍵資源),此外還要壓縮和優化各項資源,確保最大限度減少傳送大小。

優化關鍵渲染路徑的常規步驟以下:
(1)對關鍵路徑進行分析和特性描述:資源數、字節數、長度。
(2)最大限度減小關鍵資源的數量:刪除它們,延遲它們的下載,將它們標記爲異步等。
(3)優化關鍵字節數以縮短下載時間(往返次數)。
(4)優化其他關鍵資源的加載順序:您須要儘早下載全部關鍵資產,以縮短關鍵路徑長度。

什麼是重繪和迴流?(瀏覽器繪製過程)

重繪:
當渲染樹中的一些元素須要更新屬性,而這些屬性只是影響元素的外觀、風格,而不會影響佈局的操做,好比 background-color,咱們將這樣的操做稱爲重繪。
迴流:
當渲染樹中的一部分(或所有)由於元素的規模尺寸、佈局、隱藏等改變而須要從新構建的操做,會影響到佈局的操做,這樣的操做咱們稱爲迴流。

任何會改變元素幾何信息(元素的位置和尺寸大小)的操做,都會觸發迴流。
會致使迴流的操做:

  • 頁面首次渲染
  • 添加或者刪除可見的 DOM 元素;
  • 元素尺寸改變——邊距、填充、邊框、寬度和高度
  • 內容變化,好比用戶在 input 框中輸入文字
  • 瀏覽器窗口尺寸改變——resize事件發生時
  • 計算 offsetWidthoffsetHeight 屬性
  • 設置 style 屬性的值
  • 當你修改網頁的默認字體,或者字體大小變化
  • 激活CSS僞類(例如: :hover

一些經常使用致使迴流的方法:

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

迴流一定會發生重繪,重繪不必定會引起迴流。迴流所需的成本比重繪高的多,改變父節點裏的子節點極可能會致使父節點的一系列迴流。

迴流比重繪的代價要更高。
有時即便僅僅迴流一個單一的元素,它的父元素以及任何跟隨它的元素也會產生迴流。
現代瀏覽器會對頻繁的迴流或重繪操做進行優化:

瀏覽器會維護一個隊列,把全部引發迴流和重繪的操做放入隊列中,若是隊列中的任務數量或者時間間隔達到一個閾值的,瀏覽器就會將隊列清空,進行一次批處理,這樣能夠把屢次迴流和重繪變成一次。

當你訪問如下屬性或方法時,瀏覽器會馬上清空隊列:

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • widthheight
  • getComputedStyle()
  • getBoundingClientRect()

由於隊列中可能會有影響到這些屬性或方法返回值的操做,即便你但願獲取的信息與隊列中操做引起的改變無關,瀏覽器也會強行清空隊列,確保你拿到的值是最精確的。

如何減小回流?(瀏覽器繪製過程)

  • 放棄傳統操做 DOM 的時代,基於 vue/react 開始數據影響視圖模式,mvvm / mvc / virtual dom / dom diff ......vue / react
數據驅動思想 :
咱們本身不操做DOM,咱們只操做數據,讓框架幫咱們根據數據渲染視圖(框架內部自己對於DOM的迴流和重繪以及其它性能優化作的很是好)
  • 分離讀寫操做(現代瀏覽器的渲染隊列的機制)(重要)
遇到一行修改樣式的代碼,先放到渲染隊列中,繼續看 下面一行代碼 是否還爲修改樣式的,若是是繼續增長到渲染隊列中...直到下面的代碼再也不是修改樣式的,而是獲取樣式的代碼!此時再也不向渲染隊列中增長,把以前渲染隊列中要修改的樣式一次性渲染到頁面中,引起一次DOM的迴流和重繪。
  • 元素批量修改(重要)
DOM的增長也會引發迴流重繪
文檔碎片:臨時建立的一個存放文檔的容器,咱們能夠把新建立的LI,存放到容器中,當全部的LI都存儲完,咱們統一把容器中的內容增長到頁面中(只觸發一次迴流)
字符串拼接:項目中,有一個文檔碎片相似的方式,也是把要建立的LI事先存儲好,最後統一放到頁面中渲染(字符串拼接)
不要把節點的屬性值放在一個循環裏當成循環裏的變量
  • 動畫效果應用到 position 屬性爲 absolutefixed 的元素上(脫離文檔流)
也會引發迴流重繪,只不過重新計算過程當中,由於他脫離文檔流了,不會對其餘元素產生影響,從新計算的過程當中比較快一點。
  • 不要使用 table 佈局,可能很小的一個小改動會形成整個 table 的從新佈局

爲何操做 DOM 慢?(瀏覽器繪製過程)

一些 DOM 的操做或者屬性訪問可能會引發頁面的迴流和重繪,從而引發性能上的消耗。

DOMContentLoaded 事件和 Load 事件的區別?

當初始的 HTML 文檔被徹底加載和解析完成以後,DOMContentLoaded 事件被觸發,而無需等待樣式表、圖像和子框架的加載完成。
Load 事件是當全部資源加載完成後觸發的。

結合DOM文檔加載的加載步驟,DOMContentLoaded事件/Load事件,觸發時機以下:

一、解析HTML結構。  
二、加載外部腳本和樣式表文件。  
三、解析並執行腳本代碼。// 部分腳本會阻塞頁面的加載  
四、DOM樹構建完成。//DOMContentLoaded 事件  
五、加載圖片等外部文件。  
六、頁面加載完畢。//load 事件

在第4步會觸發DOMContentLoading事件,第6步觸發load事件
原生js寫法:

// 不兼容老的瀏覽器,兼容寫法見[jQuery中ready與load事件]
document.addEventListener("DOMContentLoaded", function() {
   // ...代碼...
}, false);

window.addEventListener("load", function() {
    // ...代碼...
}, false);

jQuery寫法:

// DOMContentLoaded
$(document).ready(function() {
    // ...代碼...
});

//load
$(document).load(function() {
    // ...代碼...
});

HTML5 有哪些新特性、移除了那些元素?

HTML5 如今已經不是 SGML 的子集,主要是關於圖像,位置,存儲,多任務等功能的增長。

 新增的有:
  
 繪畫 canvas;
 用於媒介回放的 video 和 audio 元素;
 本地離線存儲 localStorage 長期存儲數據,瀏覽器關閉後數據不丟失;
 sessionStorage 的數據在瀏覽器關閉後自動刪除;
 語意化更好的內容元素,好比 article、footer、header、nav、section;
 表單控件,calendar、date、time、email、url、search;
 新的技術 webworker, websocket;
 新的文檔屬性 document.visibilityState

 移除的元素有:

 純表現的元素:basefont,big,center,font, s,strike,tt,u;
 對可用性產生負面影響的元素:frame,frameset,noframes;

如何處理 HTML5 新標籤的瀏覽器兼容問題?

1) IE8/IE7/IE6 支持經過 document.createElement 方法產生的標籤,能夠利用這一特性讓這些瀏覽器
支持 HTML5 新標籤,瀏覽器支持新標籤後,還須要添加標籤默認的樣式。

(2) 固然也能夠直接使用成熟的框架,好比 html5shim ;

`<!--[if lt IE 9]>
  <script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script>
  <![endif]-->`

  [if lte IE 9]……[endif] 判斷 IE 的版本,限定只有 IE9 如下瀏覽器版本須要執行的語句。

簡述一下你對 HTML 語義化的理解?

(1) 用正確的標籤作正確的事情。
 (2) html 語義化讓頁面的內容結構化,結構更清晰,便於對瀏覽器、搜索引擎解析;
 (3) 即便在沒有樣式 CSS 狀況下也以一種文檔格式顯示,而且是容易閱讀的;
 (4) 搜索引擎的爬蟲也依賴於 HTML 標記來肯定上下文和各個關鍵字的權重,利於 SEO ;
 (5) 使閱讀源代碼的人對網站更容易將網站分塊,便於閱讀維護理解。
我認爲 html 語義化主要指的是咱們應該使用合適的標籤來劃分網頁內容的結構。html 的本質做用其實就是定義網頁文檔的結構,一個語義化的文檔,可以使頁面的結構更加清晰,易於理解。這樣不只有利於開發者的維護和理解,同時也可以使機器對文檔內容進行正確的解讀。好比說咱們經常使用的 b 標籤和 strong 標籤,它們在樣式上都是文字的加粗,可是 strong 標籤擁有強調的語義。
對於通常顯示來講,可能咱們看上去沒有差別,可是對於機器來講,就會有很大的不一樣。若是用戶使用的是屏幕閱讀器來訪問網頁的話,使用 strong 標籤就會有明顯的語調上的變化,而 b 標籤則沒有。若是是搜索引擎的爬蟲對咱們網頁進行分析的話,那麼它會依賴於 html 標籤來肯定上下文和各個關鍵字的權重,一個語義化的文檔對爬蟲來講是友好的,是有利於爬蟲對文檔內容解讀的,從而有利於咱們網站的 SEO 。從 html5 咱們能夠看出,標準是傾向於以語義化的方式來構建網頁的,好比新增了 header 、footer 這些語義標籤,刪除了 big 、font 這些沒有語義的標籤。

更多

b 與 strong 的區別和 i 與 em 的區別?

從頁面顯示效果來看,被 <b><strong> 包圍的文字將會被加粗,而被 <i><em> 包圍的文字將以斜體的形式呈現。
可是 <b> <i> 是天然樣式標籤,分別表示無心義的加粗,無心義的斜體,表現樣式爲 { font-weight: bolder},僅僅表示「這裏應該用粗體顯示」或者「這裏應該用斜體顯示」,此兩個標籤在 HTML4.01 中並不被推薦使用。
<em><strong> 是語義樣式標籤。 <em> 表示通常的強調文本,而 <strong> 表示比 <em> 語義更強的強調文本。
使用閱讀設備閱讀網頁時: <strong> 會重讀,而 <b> 是展現強調內容。

前端須要注意哪些 SEO ?

(1)合理的 title、description、keywords:搜索對着三項的權重逐個減少,title 值強調重點便可,重要關鍵詞出現不要超過2次,並且要靠前,不一樣頁面 title 要有所不一樣;description 把頁面內容高度歸納,長度合適,不可過度堆砌關鍵詞,不一樣頁面 description 有所不一樣;keywords 列舉出重要關鍵詞便可。

 (2)語義化的 HTML 代碼,符合 W3C 規範:語義化代碼讓搜索引擎容易理解網頁。

 (3)重要內容 HTML 代碼放在最前:搜索引擎抓取 HTML 順序是從上到下,有的搜索引擎對抓取長度有限制,保證重要內容確定被
     抓取。

 (4)重要內容不要用 js 輸出:爬蟲不會執行 js 獲取內容

 (5)少用 iframe:搜索引擎不會抓取 iframe 中的內容

 (6)非裝飾性圖片必須加 alt

 (7)提升網站速度:網站速度是搜索引擎排序的一個重要指標

HTML5 的離線儲存怎麼使用,工做原理能不能解釋一下?

在用戶沒有與因特網鏈接時,能夠正常訪問站點或應用,在用戶與因特網鏈接時,更新用戶機器上的緩存文件。

原理:HTML5 的離線存儲是基於一個新建的 .appcache 文件的緩存機制(不是存儲技術),經過這個文件上的解析清單離線存儲資源,這些資源就會像 cookie 同樣被存儲了下來。以後當網絡在處於離線狀態下時,瀏覽器會經過被離線存儲的數據進行頁面展現。

如何使用:

 (1)建立一個和 html 同名的 manifest 文件,而後在頁面頭部像下面同樣加入一個 manifest 的屬性。

     <html lang="en" manifest="index.manifest">

 (2)在以下 cache.manifest 文件的編寫離線存儲的資源。
       CACHE MANIFEST
       #v0.11
       CACHE:
       js/app.js
       css/style.css
       NETWORK:
       resourse/logo.png
       FALLBACK:
       / /offline.html
CACHE: 表示須要離線存儲的資源列表,因爲包含 manifest 文件的頁面將被自動離線存儲,因此不須要把頁面自身也列出來。
 NETWORK: 表示在它下面列出來的資源只有在在線的狀況下才能訪問,他們不會被離線存儲,因此在離線狀況下沒法使用這些資源。不過,若是在 CACHE 和 NETWORK 中有一個相同的資源,那麼這個資源仍是會被離線存儲,也就是說 CACHE 的優先級更高。
 FALLBACK: 表示若是訪問第一個資源失敗,那麼就使用第二個資源來替換他,好比上面這個文件表示的就是若是訪問根目錄下任何一個資源失敗了,那麼就去訪問 offline.html 。

在離線狀態時,操做 window.applicationCache 進行離線緩存的操做。

如何更新緩存:

(1)更新 manifest 文件
(2)經過 javascript 操做
(3)清除瀏覽器緩存

注意事項:

(1)瀏覽器對緩存數據的容量限制可能不太同樣(某些瀏覽器設置的限制是每一個站點 5MB)。
(2)若是 manifest 文件,或者內部列舉的某一個文件不能正常下載,整個更新過程都將失敗,瀏覽器繼續所有使用老的緩存。
(3)引用 manifest 的 html 必須與 manifest 文件同源,在同一個域下。
(4)FALLBACK 中的資源必須和 manifest 文件同源。
(5)當一個資源被緩存後,該瀏覽器直接請求這個絕對路徑也會訪問緩存中的資源。
(6)站點中的其餘頁面即便沒有設置 manifest 屬性,請求的資源若是在緩存中也從緩存中訪問。
(7)當 manifest 文件發生改變時,資源請求自己也會觸發更新。

瀏覽器是怎麼對 HTML5 的離線儲存資源進行管理和加載的呢?

在線的狀況下,瀏覽器發現 html 頭部有 manifest 屬性,它會請求 manifest 文件,若是是第一次訪問 app ,那麼瀏覽器就會根據 manifest 文件的內容下載相應的資源而且進行離線存儲。若是已經訪問過 app 而且資源已經離線存儲了,那麼瀏覽器就會使用離線的資源加載頁面,而後瀏覽器會對比新的 manifest 文件與舊的 manifest 文件,若是文件沒有發生改變,就不作 任何操做,若是文件改變了,那麼就會從新下載文件中的資源並進行離線存儲。
離線的狀況下,瀏覽器就直接使用離線存儲的資源。
~~

常見的瀏覽器端的存儲技術有哪些?

瀏覽器常見的存儲技術有 cookie、localStorage 和 sessionStorage。
還有兩種存儲技術用於大規模數據存儲,webSQL(已被廢除)和 indexDB。
IE 支持 userData 存儲數據,可是基本不多使用到,除非有很強的瀏覽器兼容需求。

cookie的基本通訊流程:設置cookie=>cookie被自動添加到request header中 => 服務端接收到cookie
關於cookie

請描述一下 cookies,sessionStorage 和 localStorage 的區別?

SessionStorage, LocalStorage, Cookie 這三者均可以被用來在瀏覽器端存儲數據,並且都是字符串類型的鍵值對。區別在於前二者屬於 HTML5 WebStorage,建立它們的目的便於客戶端存儲數據。而 cookie 是網站爲了標示用戶身份而儲存在用戶本地終端上的數據(一般通過加密)。cookie 數據始終在同源(協議、主機、端口相同)的 http 請求中攜帶(即便不須要),會在瀏覽器和服務器間來回傳遞。

  • 存儲大小:

    cookie 數據大小不能超過4 k 。
    sessionStorage 和 localStorage 雖然也有存儲大小的限制,但比 cookie 大得多,能夠達到 5M 或更大。

  • 有期時間:

    localStorage 存儲持久數據,瀏覽器關閉後數據不丟失除非主動刪除數據。
    sessionStorage 數據在頁面會話結束時會被清除。頁面會話在瀏覽器打開期間一直保持,而且從新加載或恢復頁面仍會保持原來的頁面會話。在新標籤或窗口打開一個頁面時會在頂級瀏覽上下文中初始化一個新的會話。
    cookie設置的 cookie 過時時間以前一直有效,即便窗口或瀏覽器關閉。

  • 做用域:

    sessionStorage 只在同源的同學口(或標籤頁)中共享數據,也就是隻在當前會話中共享。
    localStorage 在全部同源窗口中都是共享的。
    cookie 在全部同源窗口中都是共享的。

瀏覽器端經常使用的存儲技術是 cookielocalStoragesessionStorage

cookie 其實最開始是服務器端用於記錄用戶狀態的一種方式,由服務器設置,在客戶端存儲,而後每次發起同源請求時,發送給服務器端。cookie 最多能存儲 4 k 數據,它的生存時間由 expires 屬性指定,而且 cookie 只能被同源的頁面訪問共享。

sessionStorage 是 html5 提供的一種瀏覽器本地存儲的方法,它借鑑了服務器端 session 的概念,表明的是一次會話中所保存的數據。它通常可以存儲 5M 或者更大的數據,它在當前窗口關閉後就失效了,而且 sessionStorage 只能被同一個窗口的同源頁面所訪問共享。

localStorage 也是 html5 提供的一種瀏覽器本地存儲的方法,它通常也可以存儲 5M 或者更大的數據。它和 sessionStorage不一樣的是,除非手動刪除它,不然它不會失效,而且localStorage 也只能被同源頁面所訪問共享。

上面幾種方式都是存儲少許數據的時候的存儲方式,當咱們須要在本地存儲大量數據的時候,咱們可使用瀏覽器的 indexDB 這是瀏覽器提供的一種本地的數據庫存儲機制。它不是關係型數據庫,它內部採用對象倉庫的形式存儲數據,它更接近 NoSQL 數據庫。

indexDB

Label 的做用是什麼?是怎麼用的?

label 標籤來定義表單控制間的關係,當用戶選擇該標籤時,瀏覽器會自動將焦點轉到和標籤相關的表單控件上。

 <label for="Name">Number:</label>
 <input type=「text「 name="Name" id="Name"/>

HTML5 的 form 的自動完成功能是什麼?

autocomplete 屬性規定輸入字段是否應該啓用自動完成功能。默認爲啓用,設置爲 autocomplete=off 能夠關閉該功能。
自動完成容許瀏覽器預測對字段的輸入。當用戶在字段開始鍵入時,瀏覽器基於以前鍵入過的值,應該顯示出在字段中填寫的選項。
autocomplete 屬性適用於 <form>,以及下面的 <input> 類型:text, search, url, telephone, email, password, datepickers, range 以及 color。

如何實現瀏覽器內多個標籤頁之間的通訊?

(1)使用 WebSocket,通訊的標籤頁鏈接同一個服務器,發送消息到服務器後,服務器推送消息給全部鏈接的客戶端。

(2)使用 SharedWorker (只在 chrome 瀏覽器實現了),兩個頁面共享同一個線程,經過向線程發送數據和接收數據來實現標籤頁之間的雙向通行。

(3)能夠調用 localStorage、cookies 等本地存儲方式,localStorge 另外一個瀏覽上下文裏被添加、修改或刪除時,它都會觸發一個 storage 事件,咱們經過監聽 storage 事件,控制它的值來進行頁面信息通訊;

(4)若是咱們可以得到對應標籤頁的引用,經過 postMessage 方法也是能夠實現多個標籤頁通訊的。

實現多個標籤頁之間的通訊,本質上都是經過中介者模式來實現的。由於標籤頁之間沒有辦法直接通訊,所以咱們能夠找一箇中介者,
讓標籤頁和中介者進行通訊,而後讓這個中介者來進行消息的轉發。

第一種實現的方式是使用 websocket 協議,由於 websocket 協議能夠實現服務器推送,因此服務器就能夠用來當作這個中介者。
標籤頁經過向服務器發送數據,而後由服務器向其餘標籤頁推送轉發。

第二種是使用 ShareWorker 的方式,shareWorker 會在頁面存在的生命週期內建立一個惟一的線程,而且開啓多個頁面也只會使
用同一個線程。這個時候共享線程就能夠充當中介者的角色。標籤頁間經過共享一個線程,而後經過這個共享的線程來實現數據的交
換。

第三種方式是使用 localStorage 的方式,咱們能夠在一個標籤頁對 localStorage 的變化事件進行監聽,而後當另外一個標籤頁
修改數據的時候,咱們就能夠經過這個監聽事件來獲取到數據。這個時候 localStorage 對象就是充當的中介者的角色。

還有一種方式是使用 postMessage 方法,若是咱們可以得到對應標籤頁的引用,咱們就可使用 postMessage 方法,進行通訊。

websocket

什麼是WebSocket?

HTML5開始提供的一種瀏覽器與服務器進行全雙工通信的網絡技術,屬於應用層協議。它基於TCP傳輸協議,並複用HTTP的握手通道。
其實只要記住幾點:

  1. WebSocket能夠在瀏覽器裏使用
  2. 支持雙向通訊
  3. 使用很簡單
WebSocket優勢

說到優勢,這裏的對比參照物是HTTP協議,歸納地說就是:支持雙向通訊,更靈活,更高效,可擴展性更好。

  1. 支持雙向通訊,實時性更強。
  2. 更好的二進制支持。
  3. 較少的控制開銷。鏈接建立後,ws客戶端、服務端進行數據交換時,協議控制的數據包頭部較小。在不包含頭部的狀況下,服務端到客戶端的包頭只有2~10字節(取決於數據包長度),客戶端到服務端的的話,須要加上額外的4字節的掩碼。而HTTP協議每次通訊都須要攜帶完整的頭部。
  4. 支持擴展。ws協議定義了擴展,用戶能夠擴展協議,或者實現自定義的子協議。(好比支持自定義壓縮算法等)
WebSocket如何創建鏈接

WebSocket複用了HTTP的握手通道。具體指的是,客戶端經過HTTP請求與WebSocket服務端協商升級協議。協議升級完成後,後續的數據交換則遵守WebSocket的協議。

客戶端:申請協議升級

首先,客戶端發起協議升級請求。能夠看到,採用的是標準的HTTP報文格式,且只支持GET方法。

GET  / HTTP/1.1  
Host: localhost:8080  
Origin: http://127.0.0.1:3000  
Connection: Upgrade  
Upgrade: websocket  
Sec-WebSocket-Version: 13  
Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw==```
  • Connection: Upgrade:表示要升級協議
  • Upgrade: websocket:表示要升級到websocket協議。
  • Sec-WebSocket-Version: 13:表示websocket的版本。若是服務端不支持該版本,須要返回一個Sec-WebSocket-Version header,裏面包含服務端支持的版本號。
  • Sec-WebSocket-Key:與後面服務端響應首部的Sec-WebSocket-Accept是配套的,提供基本的防禦,好比惡意的鏈接,或者無心的鏈接。
注意,上面請求省略了部分非重點請求首部。因爲是標準的HTTP請求,相似Host、Origin、Cookie等請求首部會照常發送。在握手階段,能夠經過相關請求首部進行 安全限制、權限校驗等。
服務端:響應協議升級

服務端返回內容以下,狀態代碼101表示協議切換。到此完成協議升級,後續的數據交互都按照新的協議來。

HTTP/1.1 101 Switching Protocols  
Connection: Upgrade 
Upgrade: websocket  
Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU=

備註:每一個header都以\r\n結尾,而且最後一行加上一個額外的空行\r\n。此外,服務端迴應的HTTP狀態碼只能在握手階段使用。過了握手階段後,就只能採用特定的錯誤碼。

Sec-WebSocket-Accept的計算

Sec-WebSocket-Accept根據客戶端請求首部的Sec-WebSocket-Key計算出來。

計算公式爲:

  1. Sec-WebSocket-Key258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。
  2. 經過SHA1計算出摘要,並轉成base64字符串。

僞代碼以下:

toBase64( sha1( Sec-WebSocket-Key + 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ))
數據幀格式

客戶端、服務端數據的交換,離不開數據幀格式的定義。所以,在實際講解數據交換以前,咱們先來看下WebSocket的數據幀格式。

WebSocket客戶端、服務端通訊的最小單位是幀(frame),由1個或多個幀組成一條完整的消息(message

  1. 發送端:將消息切割成多個幀,併發送給服務端;
  2. 接收端:接收消息幀,並將關聯的幀從新組裝成完整的消息;

WechatIMG13606.jpeg

Mask: 1個比特。
表示是否要對數據載荷進行掩碼操做。從客戶端向服務端發送數據時,須要對數據進行掩碼操做;從服務端向客戶端發送數據時,不須要對數據進行掩碼操做。若是服務端接收到的數據沒有進行過掩碼操做,服務端須要斷開鏈接。
若是Mask是1,那麼在Masking-key中會定義一個掩碼鍵(masking key),並用這個掩碼鍵來對數據載荷進行反掩碼。全部客戶端發送到服務端的數據幀,Mask都是1。
數據傳遞
FIN:1個比特。
若是是1,表示這是消息(message)的最後一個分片(fragment),若是是0,表示不是是消息(message)的最後一個分片(fragment)。
RSV1, RSV2, RSV3:各佔1個比特。
通常狀況下全爲0。當客戶端、服務端協商採用WebSocket擴展時,這三個標誌位能夠非0,且值的含義由擴展進行定義。若是出現非零的值,且並無採用WebSocket擴展,鏈接出錯。
Opcode: 4個比特。
操做代碼,Opcode的值決定了應該如何解析後續的數據載荷(data payload)。若是操做代碼是不認識的,那麼接收端應該斷開鏈接(fail the connection)。

數據傳遞
一旦WebSocket客戶端、服務端創建鏈接後,後續的操做都是基於數據幀的傳遞。
WebSocket根據 opcode來區分操做的類型。好比 0x8表示斷開鏈接, 0x0- 0x2表示數據交互。

一、數據分片

WebSocket的每條消息可能被切分紅多個數據幀。當WebSocket的接收方收到一個數據幀時,會根據 FIN的值來判斷,是否已經收到消息的最後一個數據幀。

FIN=1表示當前數據幀爲消息的最後一個數據幀,此時接收方已經收到完整的消息,能夠對消息進行處理。FIN=0,則接收方還須要繼續監聽接收其他的數據幀。

此外,opcode在數據交換的場景下,表示的是數據的類型。0x01表示文本,0x02表示二進制。而0x00比較特殊,表示延續幀(continuation frame),顧名思義,就是完整消息對應的數據幀還沒接收完。

二、數據分片例子

FIN=1, 表示是當前消息的最後一個數據幀。服務端收到當前數據幀後,能夠處理消息。opcode=0x1,表示客戶端發送的是文本類型。
舉例

  1. FIN=0,opcode=0x1,表示發送的是文本類型,且消息還沒發送完成,還有後續的數據幀。
  2. FIN=0,opcode=0x0,表示消息還沒發送完成,還有後續的數據幀,當前的數據幀須要接在上一條數據幀以後。
  3. FIN=1,opcode=0x0,表示消息已經發送完成,沒有後續的數據幀,當前的數據幀須要接在上一條數據幀以後。服務端能夠將關聯的數據幀組裝成完整的消息。
鏈接保持+心跳

WebSocket爲了保持客戶端、服務端的實時雙向通訊,須要確保客戶端、服務端之間的TCP通道保持鏈接沒有斷開。然而,對於長時間沒有數據往來的鏈接,若是依舊長時間保持着,可能會浪費包括的鏈接資源。
但不排除有些場景,客戶端、服務端雖然長時間沒有數據往來,但仍須要保持鏈接。這個時候,能夠採用心跳來實現。

  • 發送方->接收方:ping
  • 接收方->發送方:pong

ping、pong的操做,對應的是WebSocket的兩個控制幀,opcode分別是0x90xA

舉例,WebSocket服務端向客戶端發送ping,只須要以下代碼(採用ws模塊)

ws.ping('', false, true);
Sec-WebSocket-Key/Accept的做用

前面提到了,Sec-WebSocket-Key/Sec-WebSocket-Accept在主要做用在於提供基礎的防禦,減小惡意鏈接、意外鏈接。

做用大體概括以下:

  1. 避免服務端收到非法的websocket鏈接(好比http客戶端不當心請求鏈接websocket服務,此時服務端能夠直接拒絕鏈接)
  2. 確保服務端理解websocket鏈接。由於ws握手階段採用的是http協議,所以可能ws鏈接是被一個http服務器處理並返回的,此時客戶端能夠經過Sec-WebSocket-Key來確保服務端認識ws協議。(並不是百分百保險,好比老是存在那麼些無聊的http服務器,光處理Sec-WebSocket-Key,但並無實現ws協議。。。)
  3. 用瀏覽器裏發起ajax請求,設置header時,Sec-WebSocket-Key以及其餘相關的header是被禁止的。這樣能夠避免客戶端發送ajax請求時,意外請求協議升級(websocket upgrade
  4. 能夠防止反向代理(不理解ws協議)返回錯誤的數據。好比反向代理先後收到兩次ws鏈接的升級請求,反向代理把第一次請求的返回給cache住,而後第二次請求到來時直接把cache住的請求給返回(無心義的返回)。
  5. Sec-WebSocket-Key主要目的並非確保數據的安全性,由於Sec-WebSocket-KeySec-WebSocket-Accept的轉換計算公式是公開的,並且很是簡單,最主要的做用是預防一些常見的意外狀況(非故意的)。
強調:Sec-WebSocket-Key/Sec-WebSocket-Accept 的換算,只能帶來基本的保障,但鏈接是否安全、數據是否安全、客戶端/服務端是否合法的 ws客戶端、ws服務端,其實並無實際性的保證。

JS

介紹 js 的基本數據類型。

js 一共有六種基本數據類型,分別是 Undefined、Null、Boolean、Number、String,還有在 ES6 中新增的 Symbol 類型,表明建立後獨一無二且不可變的數據類型,它的出現我認爲主要是爲了解決可能出現的全局變量衝突的問題。

JavaScript 有幾種類型的值?你能畫一下他們的內存圖嗎?

js 能夠分爲兩種類型的值,一種是基本數據類型,一種是複雜數據類型。
基本數據類型(Undefined、Null、Boolean、Number、String)
複雜數據類型指的是 Object 類型,全部其餘的如 Array、Date 等數據類型均可以理解爲 Object 類型的子類。

棧類型:
屏幕快照 2020-05-17 下午12.50.09.png
堆類型:
屏幕快照 2020-05-17 下午12.50.23.png

兩種類型間的主要區別是它們的存儲位置不一樣
基本數據類型的值直接保存在棧中
複雜數據類型的值保存在堆中,經過使用在棧中保存對應的指針來獲取堆中的值。

什麼是堆?什麼是棧?它們之間有什麼區別和聯繫?

堆和棧的概念存在於數據結構中和操做系統內存中。

在數據結構中
棧中數據的存取方式爲先進後出。而堆是一個優先隊列,是按優先級來進行排序的,優先級能夠按照大小來規定。徹底二叉樹是堆的一種實現方式。

在操做系統中,內存被分爲棧區和堆區。
棧區內存由編譯器自動分配釋放,存放函數的參數值,局部變量的值等。其操做方式相似於數據結構中的棧。
堆區內存通常由程序員分配釋放,若程序員不釋放,程序結束時可能由垃圾回收機制回收。

內部屬性 [[Class]] 是什麼?

全部 typeof 返回值爲 "object" 的對象(如數組)都包含一個內部屬性 [[Class]](咱們能夠把它看做一個內部的分類,而非傳統的面向對象意義上的類)。這個屬性沒法直接訪問,通常經過 Object.prototype.toString(..) 來查看。例如:
Object.prototype.toString.call( [1,2,3] );
// "[object Array]"
Object.prototype.toString.call( /regex-literal/i );
// "[object RegExp]"

介紹 js 有哪些內置對象?

js 中的內置對象主要指的是在程序執行前存在全局做用域裏的由 js 定義的一些全局值屬性、函數和用來實例化其餘對象的構造函數對象。通常咱們常常用到的如:
全局變量值 NaN、undefined,
全局函數如 parseInt()、parseFloat()
基本對象如 Object、Function、Boolean、Symbol
用來實例化對象的構造函數如 Date、Object
表示和操做字符串的對象如 String、RegExp
還有提供數學計算的單體內置對象如 Math 對象。

undefined 與 undeclared 的區別?

已在做用域中聲明但尚未賦值的變量,是 undefined 的。相反,尚未在做用域中聲明過的變量,是 undeclared 的。

對於 undeclared 變量的引用,瀏覽器會報引用錯誤,如ReferenceError: b is not defined 。可是咱們可使用 typeof 的安全防範機制來避免報錯,由於對於 undeclared(或者 not defined )變量,typeof 會返回 "undefined"。

null 和 undefined 的區別?

CSS

介紹一下標準的 CSS 的盒子模型?低版本 IE 的盒子模型有什麼不一樣的?

盒模型都是由四個部分組成的,分別是margin、border、padding和content。
標準盒模型和IE盒模型的區別在於設置width和height時,所對應的範圍不一樣。標準盒模型的width和height屬性的範圍只包含了content,而IE盒模型的width和height屬性的範圍包含了border、padding和content。

css的盒模型由content(內容)、padding(內邊距)、border(邊框)、margin(外邊距)組成。但盒子的大小由content+padding+border這幾部分決定,把margin算進去的那是盒子佔據的位置,而不是盒子的大小

通常來講,咱們能夠經過修改元素的box-sizing屬性來改變元素的盒模型。

CSS 選擇符有哪些

(1)id選擇器(#myid)
(2)類選擇器(.myclassname)
(3)標籤選擇器(div,h1,p)
(4)後代選擇器(h1p)
(5)相鄰後代選擇器(子)選擇器(ul>li)
(6)兄弟選擇器(li~a)
(7)相鄰兄弟選擇器(li+a)
(8)屬性選擇器(a[rel="external"])
(9)僞類選擇器(a:hover,li:nth-child)
(10)僞元素選擇器(::before、::after)
(11)通配符選擇器(*)

::before 和:after 中雙冒號和單冒號有什麼區別?解釋一下這 2 個僞元素的做用

在css3中使用單冒號來表示僞類,用雙冒號來表示僞元素。可是爲了兼容已有的僞元素的寫法,在一些瀏覽器中也可使用單冒號來表示僞元素。

僞類通常匹配的是元素的一些特殊狀態,如hover、link等,而僞元素通常匹配的特殊的位置,好比after、before等。

僞類與僞元素的區別

css引入僞類和僞元素概念是爲了格式化文檔樹之外的信息。也就是說,僞類和僞元素是用來修飾不在文檔樹中的部分,好比,一句話中的第一個字母,或者是列表中的第一個元素。

僞類用於當已有的元素處於某個狀態時,爲其添加對應的樣式,這個狀態是根據用戶行爲而動態變化的。好比說,當用戶懸停在指定的元素時,咱們能夠經過 :hover來描述這個元素的狀態。

僞元素用於建立一些不在文檔樹中的元素,併爲其添加樣式。它們容許咱們爲元素的某些部分設置樣式。好比說,咱們能夠經過::before來在一個元素前增長一些文本,併爲這些文本添加樣式。雖然用戶能夠看到這些文本,可是這些文本實際上不在文檔樹中。

有時你會發現僞元素使用了兩個冒號(::)而不是一個冒號(:)。這是CSS3的一部分,並嘗試區分僞類和僞元素。大多數瀏覽器都支持這兩個值。按照規則應該使用(::)而不是(:),從而區分僞類和僞元素。可是,因爲在舊版本的W3C規範並未對此進行特別區分,所以目前絕大多數的瀏覽器都支持使用這兩種方式表示僞元素。

相關文章
相關標籤/搜索