2020年-web前端-最新-最全-最快的面試諮詢-面試真題-面試常考題

HTML 面試知識點總結

本部分主要是筆者在複習 HTML 相關知識和一些相關面試題時所做的筆記,如果出現錯誤,希望大家指出!

目錄

1. DOCTYPE 的作用是什麼?

相關知識點:

IE5.5 引入了文檔模式的概念,而這個概念是通過使用文檔類型(DOCTYPE)切換實現的。

<!DOCTYPE>聲明位於 HTML 文檔中的第一行,處於 <html> 標籤之前。告知瀏覽器的解析器用什麼文檔標準解析這個文檔。

DOCTYPE 不存在或格式不正確會導致文檔以兼容模式呈現。

回答(參考1-5):

<!DOCTYPE>  聲明一般位於文檔的第一行,它的作用主要是告訴瀏覽器以什麼樣的模式來解析文檔。一般指定了之後會以標準模式來
進行文檔解析,否則就以兼容模式進行解析。在標準模式下,瀏覽器的解析規則都是按照最新的標準進行解析的。而在兼容模式下,瀏
覽器會以向後兼容的方式來模擬老式瀏覽器的行爲,以保證一些老的網站的正確訪問。

在 html5 之後不再需要指定 DTD 文檔,因爲 html5 以前的 html 文檔都是基於 SGML 的,所以需要通過指定 DTD 來定義文
檔中允許的屬性以及一些規則。而 html5 不再基於 SGML 了,所以不再需要使用 DTD。

2. 標準模式與兼容模式各有什麼區別?

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

3. HTML5 爲什麼只需要寫 ``,而不需要引入 DTD?

HTML5 不基於 SGML,因此不需要對 DTD 進行引用,但是需要 DOCTYPE 來規範瀏覽器的行爲(讓瀏覽器按照它們應該的方式來運
行)。

而 HTML4.01 基於 SGML ,所以需要對 DTD 進行引用,才能告知瀏覽器文檔所使用的文檔類型。

4. SGML 、 HTML 、XML 和 XHTML 的區別?

SGML 是標準通用標記語言,是一種定義電子文檔結構和描述其內容的國際標準語言,是所有電子文檔標記語言的起源。

HTML 是超文本標記語言,主要是用於規定怎麼顯示網頁。

XML 是可擴展標記語言是未來網頁語言的發展方向,XML 和 HTML 的最大區別就在於 XML 的標籤是可以自己創建的,數量無限多,
而 HTML 的標籤都是固定的而且數量有限。

XHTML 也是現在基本上所有網頁都在用的標記語言,他其實和 HTML 沒什麼本質的區別,標籤都一樣,用法也都一樣,就是比 HTML 
更嚴格,比如標籤必須都用小寫,標籤都必須有閉合標籤等。

5. DTD 介紹

DTD( Document Type Definition 文檔類型定義)是一組機器可讀的規則,它們定義 XML 或 HTML 的特定版本中所有允許元
素及它們的屬性和層次關係的定義。在解析網頁時,瀏覽器將使用這些規則檢查頁面的有效性並且採取相應的措施。

DTD 是對 HTML 文檔的聲明,還會影響瀏覽器的渲染模式(工作模式)。

6. 行內元素定義

HTML4 中,元素被分成兩大類: inline (內聯元素)與 block(塊級元素)。一個行內元素只佔據它對應標籤的邊框所包含的空
間。

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

7. 塊級元素定義

塊級元素佔據其父元素(容器)的整個寬度,因此創建了一個“塊”。

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

8. 行內元素與塊級元素的區別?

HTML4中,元素被分成兩大類:inline (內聯元素)與 block (塊級元素)。

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

9. 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 Interactive

10. 空元素定義

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

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

11. link 標籤定義

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

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

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

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

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

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

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

(4)DOM 可控性區別。可以通過 JS 操作 DOM ,插入 link 標籤來改變樣式;由於 DOM 方法是基於文檔的,無法使用 @i
    mport 的方式插入樣式。

13. 你對瀏覽器的理解?

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

HTML 和 CSS 規範中規定了瀏覽器解釋 html 文檔的方式,由 W3C 組織對這些規範進行維護,W3C 是負責制定 web 標準的
組織。

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

簡單來說瀏覽器可以分爲兩部分,shell 和 內核。

其中 shell 的種類相對比較多,內核則比較少。shell 是指瀏覽器的外殼:例如菜單,工具欄等。主要是提供給用戶界面操作,
參數設置等等。它是調用內核來實現各種功能的。內核纔是瀏覽器的核心。內核是基於標記語言顯示內容的程序或模塊。也有一些
 瀏覽器並不區分外殼和內核。從 Mozilla 將 Gecko 獨立出來後,纔有了外殼和內核的明確劃分。

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

主要分成兩部分:渲染引擎和 JS 引擎。

渲染引擎的職責就是渲染,即在瀏覽器窗口中顯示所請求的內容。默認情況下,渲染引擎可以顯示 html、xml 文檔及圖片,它也
可以藉助插件(一種瀏覽器擴展)顯示其他類型數據,例如使用 PDF 閱讀器插件,可以顯示 PDF 格式。

JS 引擎:解析和執行 javascript 來實現網頁的動態效果。

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

15. 常見的瀏覽器內核比較

Trident:這種瀏覽器內核是 IE 瀏覽器用的內核,因爲在早期 IE 佔有大量的市場份額,所以這種內核比較流行,以前有很多
網頁也是根據這個內核的標準來編寫的,但是實際上這個內核對真正的網頁標準支持不是很好。但是由於 IE 的高市場佔有率,微
軟也很長時間沒有更新 Trident 內核,就導致了 Trident 內核和 W3C 標準脫節。還有就是 Trident 內核的大量 Bug 等
安全問題沒有得到解決,加上一些專家學者公開自己認爲 IE 瀏覽器不安全的觀點,使很多用戶開始轉向其他瀏覽器。

Gecko:這是 Firefox 和 Flock 所採用的內核,這個內核的優點就是功能強大、豐富,可以支持很多複雜網頁效果和瀏覽器擴
展接口,但是代價是也顯而易見就是要消耗很多的資源,比如內存。

Presto:Opera 曾經採用的就是 Presto 內核,Presto 內核被稱爲公認的瀏覽網頁速度最快的內核,這得益於它在開發時的
天生優勢,在處理 JS 腳本等腳本語言時,會比其他的內核快3倍左右,缺點就是爲了達到很快的速度而丟掉了一部分網頁兼容性。

Webkit:Webkit 是 Safari 採用的內核,它的優點就是網頁瀏覽速度較快,雖然不及 Presto 但是也勝於 Gecko 和 Trid
ent,缺點是對於網頁代碼的容錯性不高,也就是說對網頁代碼的兼容性較低,會使一些編寫不標準的網頁無法正確顯示。WebKit 
前身是 KDE 小組的 KHTML 引擎,可以說 WebKit 是 KHTML 的一個開源的分支。

Blink:谷歌在 Chromium Blog 上發表博客,稱將與蘋果的開源瀏覽器核心 Webkit 分道揚鑣,在 Chromium 項目中研發 B
link 渲染引擎(即瀏覽器核心),內置於 Chrome 瀏覽器之中。其實 Blink 引擎就是 Webkit 的一個分支,就像 webkit 是
KHTML 的分支一樣。Blink 引擎現在是谷歌公司與 Opera Software 共同研發,上面提到過的,Opera 棄用了自己的 Presto 
內核,加入 Google 陣營,跟隨谷歌一起研發 Blink。

詳細的資料可以參考: 《瀏覽器內核的解析和對比》 《五大主流瀏覽器內核的源起以及國內各大瀏覽器內核總結》

16. 常見瀏覽器所用內核

 (1) IE 瀏覽器內核:Trident 內核,也是俗稱的 IE 內核;

 (2) Chrome 瀏覽器內核:統稱爲 Chromium 內核或 Chrome 內核,以前是 Webkit 內核,現在是 Blink內核;

 (3) Firefox 瀏覽器內核:Gecko 內核,俗稱 Firefox 內核;

 (4) Safari 瀏覽器內核:Webkit 內核;

 (5) Opera 瀏覽器內核:最初是自己的 Presto 內核,後來加入谷歌大軍,從 Webkit 又到了 Blink 內核;

 (6) 360瀏覽器、獵豹瀏覽器內核:IE + Chrome 雙內核;

 (7) 搜狗、遨遊、QQ 瀏覽器內核:Trident(兼容模式)+ Webkit(高速模式);

 (8) 百度瀏覽器、世界之窗內核:IE 內核;

 (9) 2345瀏覽器內核:好像以前是 IE 內核,現在也是 IE + Chrome 雙內核了;

 (10)UC 瀏覽器內核:這個衆口不一,UC 說是他們自己研發的 U3 內核,但好像還是基於 Webkit 和 Trident ,還有說
      是基於火狐內核。

17. 瀏覽器的渲染原理?

 (1)首先解析收到的文檔,根據文檔定義構建一棵 DOM 樹,DOM 樹是由 DOM 元素及屬性節點組成的。

 (2)然後對 CSS 進行解析,生成 CSSOM 規則樹。

 (3)根據 DOM 樹和 CSSOM 規則樹構建渲染樹。渲染樹的節點被稱爲渲染對象,渲染對象是一個包含有顏色和大小等屬性的矩
     形,渲染對象和 DOM 元素相對應,但這種對應關係不是一對一的,不可見的 DOM 元素不會被插入渲染樹。還有一些 DOM 
     元素對應幾個可見對象,它們一般是一些具有複雜結構的元素,無法用一個矩形來描述。

 (4)當渲染對象被創建並添加到樹中,它們並沒有位置和大小,所以當瀏覽器生成渲染樹以後,就會根據渲染樹來進行佈局(也
     可以叫做迴流)。這一階段瀏覽器要做的事情是要弄清楚各個節點在頁面中的確切位置和大小。通常這一行爲也被稱爲“自動
     重排”。

 (5)佈局階段結束後是繪製階段,遍歷渲染樹並調用渲染對象的 paint 方法將它們的內容顯示在屏幕上,繪製使用 UI 基礎組
     件。

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

詳細資料可以參考: 《瀏覽器渲染原理》 《瀏覽器的渲染原理簡介》 《前端必讀:瀏覽器內部工作原理》 《深入淺出瀏覽器渲染原理》

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

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

 也就是說,如果你想首屏渲染的越快,就越不應該在首屏就加載 JS 文件,這也是都建議將 script 標籤放在 body 標籤底部的
 原因。當然在當下,並不是說 script 標籤必須放在底部,因爲你可以給 script 標籤添加 defer 或者 async 屬性。

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

 (1)腳本沒有 defer 或 async,瀏覽器會立即加載並執行指定的腳本,也就是說不等待後續載入的文檔元素,讀到就加載並執
     行。

 (2)defer 屬性表示延遲執行引入的 JavaScript,即這段 JavaScript 加載時 HTML 並未停止解析,這兩個過程是並行的。
     當整個 document 解析完畢後再執行腳本文件,在 DOMContentLoaded 事件觸發之前完成。多個腳本按順序執行。

 (3)async 屬性表示異步執行引入的 JavaScript,與 defer 的區別在於,如果已經加載好,就會開始執行,也就是說它的執
     行仍然會阻塞文檔的解析,只是它的加載過程不會阻塞。多個腳本的執行順序無法保證。

詳細資料可以參考: 《defer 和 async 的區別》

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

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

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

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

 所以如果瀏覽器尚未完成 CSSOM 的下載和構建,而我們卻想在此時運行腳本,那麼瀏覽器將延遲 JavaScript 腳本執行和文檔
 的解析,直至其完成 CSSOM 的下載和構建。也就是說,在這種情況下,瀏覽器會先下載和構建 CSSOM,然後再執行 JavaScript,
 最後再繼續文檔的解析。

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

 FOUC:主要指的是樣式閃爍的問題,由於瀏覽器渲染機制(比如firefox),在 CSS 加載之前,先呈現了 HTML,就會導致展示
       出無樣式內容,然後樣式突然呈現的現象。會出現這個問題的原因主要是 css 加載時間過長,或者 css 被放在了文檔底
       部。

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

詳細資料可以參考: 《前端魔法堂:解祕 FOUC》 《白屏問題和 FOUC》

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

 爲儘快完成首次渲染,我們需要最大限度減小以下三種可變因素:

 (1)關鍵資源的數量。
 (2)關鍵路徑長度。
 (3)關鍵字節的數量。

 關鍵資源是可能阻止網頁首次渲染的資源。這些資源越少,瀏覽器的工作量就越小,對 CPU 以及其他資源的佔用也就越少。

 同樣,關鍵路徑長度受所有關鍵資源與其字節大小之間依賴關係圖的影響:某些資源只能在上一資源處理完畢之後才能開始下載,
 並且資源越大,下載所需的往返次數就越多。

 最後,瀏覽器需要下載的關鍵字節越少,處理內容並讓其出現在屏幕上的速度就越快。要減少字節數,我們可以減少資源數(將它
 們刪除或設爲非關鍵資源),此外還要壓縮和優化各項資源,確保最大限度減小傳送大小。

 優化關鍵渲染路徑的常規步驟如下:

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

詳細資料可以參考: 《優化關鍵渲染路徑》

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

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

 常見引起迴流屬性和方法:

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

 (1)添加或者刪除可見的 DOM 元素;
 (2)元素尺寸改變——邊距、填充、邊框、寬度和高度
 (3)內容變化,比如用戶在 input 框中輸入文字
 (4)瀏覽器窗口尺寸改變——resize事件發生時
 (5)計算 offsetWidth 和 offsetHeight 屬性
 (6)設置 style 屬性的值
 (7)當你修改網頁的默認字體時。

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

常見引起重繪屬性和方法:

常見引起迴流屬性和方法

常見引起迴流屬性和方法:

常見引起重繪屬性和方法

詳細資料可以參考: 《瀏覽器的迴流與重繪》

25. 如何減少迴流?(瀏覽器繪製過程)

 (1)使用 transform 替代 top

 (2)不要把節點的屬性值放在一個循環裏當成循環裏的變量

 (3)不要使用 table 佈局,可能很小的一個小改動會造成整個 table 的重新佈局

 (4)把 DOM 離線後修改。如:使用 documentFragment 對象在內存裏操作 DOM

 (5)不要一條一條地修改 DOM 的樣式。與其這樣,還不如預先定義好 css 的 class,然後修改 DOM 的 className。

26. 爲什麼操作 DOM 慢?(瀏覽器繪製過程)

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

27. DOMContentLoaded 事件和 Load 事件的區別?

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

 Load 事件是當所有資源加載完成後觸發的。

詳細資料可以參考: 《DOMContentLoaded 事件 和 Load 事件的區別?》

28. 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;

29. 如何處理 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 以下瀏覽器版本需要執行的語句。

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

相關知識點:

 (1) 用正確的標籤做正確的事情。
 (2) html 語義化讓頁面的內容結構化,結構更清晰,便於對瀏覽器、搜索引擎解析;
 (3) 即使在沒有樣式 CSS 情況下也以一種文檔格式顯示,並且是容易閱讀的;
 (4) 搜索引擎的爬蟲也依賴於 HTML 標記來確定上下文和各個關鍵字的權重,利於 SEO ;
 (5) 使閱讀源代碼的人對網站更容易將網站分塊,便於閱讀維護理解。

回答:

 我認爲 html 語義化主要指的是我們應該使用合適的標籤來劃分網頁內容的結構。html 的本質作用其實就是定義網頁文檔的結構,
 一個語義化的文檔,能夠使頁面的結構更加清晰,易於理解。這樣不僅有利於開發者的維護和理解,同時也能夠使機器對文檔內容進
 行正確的解讀。比如說我們常用的 b 標籤和 strong 標籤,它們在樣式上都是文字的加粗,但是 strong 標籤擁有強調的語義。
 對於一般顯示來說,可能我們看上去沒有差異,但是對於機器來說,就會有很大的不同。如果用戶使用的是屏幕閱讀器來訪問網頁的
 話,使用 strong 標籤就會有明顯的語調上的變化,而 b 標籤則沒有。如果是搜索引擎的爬蟲對我們網頁進行分析的話,那麼它會
 依賴於 html 標籤來確定上下文和各個關鍵字的權重,一個語義化的文檔對爬蟲來說是友好的,是有利於爬蟲對文檔內容解讀的,
 從而有利於我們網站的 SEO 。從 html5 我們可以看出,標準是傾向於以語義化的方式來構建網頁的,比如新增了 header 、fo
 oter 這些語義標籤,刪除了 big 、font 這些沒有語義的標籤。

詳細資料可以參考: 《語義化的 HTML 結構到底有什麼好處?》 《如何理解 Web 語義化?》 《我的 HTML 會說話——從實用出發,談談 HTML 的語義化》

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

 從頁面顯示效果來看,被 <b> 和 <strong> 包圍的文字將會被加粗,而被 <i> 和 <em> 包圍的文字將以斜體的形式呈現。

 但是 <b> <i> 是自然樣式標籤,分別表示無意義的加粗,無意義的斜體,表現樣式爲 { font-weight: bolder},僅僅表示「這
 裏應該用粗體顯示」或者「這裏應該用斜體顯示」,此兩個標籤在 HTML4.01 中並不被推薦使用。

 而 <em> 和 <strong> 是語義樣式標籤。 <em> 表示一般的強調文本,而 <strong> 表示比 <em> 語義更強的強調文本。
 
 使用閱讀設備閱讀網頁時:<strong> 會重讀,而 <b> 是展示強調內容。

詳細資料可以參考: 《HTML5 中的 b/strong,i/em 有什麼區別?》

32. 前端需要注意哪些 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)提高網站速度:網站速度是搜索引擎排序的一個重要指標

33. 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 中有一個相同的資源,那麼這個資源還是會被離線存儲,也就是說 C
              ACHE 的優先級更高。

     FALLBACK: 表示如果訪問第一個資源失敗,那麼就使用第二個資源來替換他,比如上面這個文件表示的就是如果訪問根目錄下
               任何一個資源失敗了,那麼就去訪問 offline.html 。

 (3)在離線狀態時,操作 window.applicationCache 進行離線緩存的操作。


 如何更新緩存:

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

 注意事項:

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

詳細的使用可以參考: 《HTML5 離線緩存-manifest 簡介》 《有趣的 HTML5:離線存儲》

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

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

 離線的情況下,瀏覽器就直接使用離線存儲的資源。

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

 瀏覽器常見的存儲技術有 cookie、localStorage 和 sessionStorage。

 還有兩種存儲技術用於大規模數據存儲,webSQL(已被廢除)和 indexDB。

 IE 支持 userData 存儲數據,但是基本很少使用到,除非有很強的瀏覽器兼容需求。

詳細的資料可以參考: 《很全很全的前端本地存儲講解》

36. 請描述一下 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          在所有同源窗口中都是共享的。

回答:

 瀏覽器端常用的存儲技術是 cookie 、localStorage 和 sessionStorage。

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

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

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

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

詳細的資料可以參考: 《請描述一下 cookies,sessionStorage 和 localStorage 的區別?》 《瀏覽器數據庫 IndexedDB 入門教程》

37. iframe 有那些缺點?

 iframe 元素會創建包含另外一個文檔的內聯框架(即行內框架)。

 主要缺點有:

 (1) iframe 會阻塞主頁面的 onload 事件。window 的 onload 事件需要在所有 iframe 加載完畢後(包含裏面的元素)才
      會觸發。在 Safari 和 Chrome 裏,通過 JavaScript 動態設置 iframe 的 src 可以避免這種阻塞情況。
 (2) 搜索引擎的檢索程序無法解讀這種頁面,不利於網頁的 SEO 。
 (3) iframe 和主頁面共享連接池,而瀏覽器對相同域的連接有限制,所以會影響頁面的並行加載。
 (4) 瀏覽器的後退按鈕失效。
 (5) 小型的移動設備無法完全顯示框架。

詳細的資料可以參考: 《使用 iframe 的優缺點》 《iframe 簡單探索以及 iframe 跨域處理》

38. Label 的作用是什麼?是怎麼用的?

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

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

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

 autocomplete 屬性規定輸入字段是否應該啓用自動完成功能。默認爲啓用,設置爲 autocomplete=off 可以關閉該功能。

 自動完成允許瀏覽器預測對字段的輸入。當用戶在字段開始鍵入時,瀏覽器基於之前鍵入過的值,應該顯示出在字段中填寫的選項。

 autocomplete 屬性適用於 <form>,以及下面的 <input> 類型:text, search, url, telephone, email, password, 
 datepickers, range 以及 color。

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

相關資料:

 (1)使用 WebSocket,通信的標籤頁連接同一個服務器,發送消息到服務器後,服務器推送消息給所有連接的客戶端。

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

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

 (4)如果我們能夠獲得對應標籤頁的引用,通過 postMessage 方法也是可以實現多個標籤頁通信的。

回答:

 實現多個標籤頁之間的通信,本質上都是通過中介者模式來實現的。因爲標籤頁之間沒有辦法直接通信,因此我們可以找一箇中介者,
 讓標籤頁和中介者進行通信,然後讓這個中介者來進行消息的轉發。

 第一種實現的方式是使用 websocket 協議,因爲 websocket 協議可以實現服務器推送,所以服務器就可以用來當做這個中介者。
 標籤頁通過向服務器發送數據,然後由服務器向其他標籤頁推送轉發。

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

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

 還有一種方式是使用 postMessage 方法,如果我們能夠獲得對應標籤頁的引用,我們就可以使用 postMessage 方法,進行通信。

詳細的資料可以參考:

《WebSocket 教程》 《WebSocket 協議:5分鐘從入門到精通》 《WebSocket 學習(一)——基於 socket.io 實現簡單多人聊天室》 《使用 Web Storage API》 《JavaScript 的多線程,Worker 和 SharedWorker》 《實現多個標籤頁之間通信的幾種方法》

41. webSocket 如何兼容低版本瀏覽器?

 Adobe Flash Socket 、
 ActiveX HTMLFile (IE) 、
 基於 multipart 編碼發送 XHR 、
 基於長輪詢的 XHR

42. 頁面可見性(Page Visibility API) 可以有哪些用途?

 這個新的 API 的意義在於,通過監聽網頁的可見性,可以預判網頁的卸載,還可以用來節省資源,減緩電能的消耗。比如,一旦用戶
 不看網頁,下面這些網頁行爲都是可以暫停的。

 (1)對服務器的輪詢
 (2)網頁動畫
 (3)正在播放的音頻或視頻

詳細資料可以參考: 《Page Visibility API 教程》

43. 如何在頁面上實現一個圓形的可點擊區域?

 (1)純 html 實現,使用 <area> 來給 <img> 圖像標記熱點區域的方式,<map> 標籤用來定義一個客戶端圖像映射,<area> 
     標籤用來定義圖像映射中的區域,area 元素永遠嵌套在 map 元素內部,我們可以將 area 區域設置爲圓形,從而實現可點擊
     的圓形區域。

 (2)純 css 實現,使用 border-radius ,當 border-radius 的長度等於寬高相等的元素值的一半時,即可實現一個圓形的
     點擊區域。

 (3)純 js 實現,判斷一個點在不在圓上的簡單算法,通過監聽文檔的點擊事件,獲取每次點擊時鼠標的位置,判斷該位置是否在我
     們規定的圓形區域內。

詳細資料可以參考: 《如何在頁面上實現一個圓形的可點擊區域?》 《HTML 標籤及在實際開發中的應用》

44. 實現不使用 border 畫出 1 px 高的線,在不同瀏覽器的標準模式與怪異模式下都能保持一致的效果。

  <div style="height:1px;overflow:hidden;background:red"></div>

45. title 與 h1 的區別?

 title 屬性沒有明確意義只表示是個標題,h1 則表示層次明確的標題,對頁面信息的抓取也有很大的影響。

46. `` 的 title 和 alt 有什麼區別?

 title 通常當鼠標滑動到元素上的時候顯示

 alt 是 <img> 的特有屬性,是圖片內容的等價描述,用於圖片無法加載時顯示、讀屏器閱讀圖片。可提圖片高可訪問性,除了純裝
 飾圖片外都必須設置有意義的值,搜索引擎會重點分析。

47. Canvas 和 SVG 有什麼區別?

 Canvas 是一種通過 JavaScript 來繪製 2D 圖形的方法。Canvas 是逐像素來進行渲染的,因此當我們對 Canvas 進行縮放時,
 會出現鋸齒或者失真的情況。
 
 SVG 是一種使用 XML 描述 2D 圖形的語言。SVG 基於 XML,這意味着 SVG DOM 中的每個元素都是可用的。我們可以爲某個元素
 附加 JavaScript 事件監聽函數。並且 SVG 保存的是圖形的繪製方法,因此當 SVG 圖形縮放時並不會失真。

詳細資料可以參考: 《SVG 與 HTML5 的 canvas 各有什麼優點,哪個更有前途?》

48. 網頁驗證碼是幹嘛的,是爲了解決什麼安全問題?

 (1)區分用戶是計算機還是人的公共全自動程序。可以防止惡意破解密碼、刷票、論壇灌水
 (2)有效防止黑客對某一個特定註冊用戶用特定程序暴力破解方式進行不斷的登陸嘗試

49. 漸進增強和優雅降級的定義

 漸進增強:針對低版本瀏覽器進行構建頁面,保證最基本的功能,然後再針對高級瀏覽器進行效果、交互等改進和追加功能達到更好的
         用戶體驗。

 優雅降級:一開始就根據高版本瀏覽器構建完整的功能,然後再針對低版本瀏覽器進行兼容。

50. attribute 和 property 的區別是什麼?

 attribute 是 dom 元素在文檔中作爲 html 標籤擁有的屬性;
 property 就是 dom 元素在 js 中作爲對象擁有的屬性。
 對於 html 的標準屬性來說,attribute 和 property 是同步的,是會自動更新的,
 但是對於自定義的屬性來說,他們是不同步的。

51. 對 web 標準、可用性、可訪問性的理解

 可用性(Usability):產品是否容易上手,用戶能否完成任務,效率如何,以及這過程中用戶的主觀感受可好,是從用戶的角度來看
 產品的質量。可用性好意味着產品質量高,是企業的核心競爭力

 可訪問性(Accessibility):Web 內容對於殘障用戶的可閱讀和可理解性
 
 可維護性(Maintainability):一般包含兩個層次,一是當系統出現問題時,快速定位並解決問題的成本,成本低則可維護性好。
 二是代碼是否容易被人理解,是否容易修改和增強功能。

52. IE 各版本和 Chrome 可以並行下載多少個資源?

 (1)  IE6 2 個併發
 (2)  iE7 升級之後的 6 個併發,之後版本也是 6 個
 (3)  Firefox,chrome 也是6個

53. Flash、Ajax 各自的優缺點,在使用中如何取捨?

 Flash:
 (1) Flash 適合處理多媒體、矢量圖形、訪問機器
 (2) 對 CSS、處理文本上不足,不容易被搜索

 Ajax:
 (1) Ajax 對 CSS、文本支持很好,支持搜索
 (2) 多媒體、矢量圖形、機器訪問不足

 共同點:
 (1) 與服務器的無刷新傳遞消息
 (2) 可以檢測用戶離線和在線狀態
 (3) 操作 DOM

54. 怎麼重構頁面?

 (1) 編寫 CSS
 (2) 讓頁面結構更合理化,提升用戶體驗
 (3) 實現良好的頁面效果和提升性能

55. 瀏覽器架構

 * 用戶界面
   * 主進程
   * 內核
       * 渲染引擎
       * JS 引擎
           * 執行棧
       * 事件觸發線程
           * 消息隊列
               * 微任務
               * 宏任務
       * 網絡異步線程
       * 定時器線程

56. 常用的 meta 標籤

 <meta> 元素可提供有關頁面的元信息(meta-information),比如針對搜索引擎和更新頻度的描述和關鍵詞。
 <meta> 標籤位於文檔的頭部,不包含任何內容。<meta> 標籤的屬性定義了與文檔相關聯的名稱/值對。

 <!DOCTYPE html>  H5標準聲明,使用 HTML5 doctype,不區分大小寫
 <head lang=”en”> 標準的 lang 屬性寫法
 <meta charset=’utf-8′>    聲明文檔使用的字符編碼
 <meta http-equiv=”X-UA-Compatible” content=”IE=edge,chrome=1″/>   優先使用 IE 最新版本和 Chrome
 <meta name=”description” content=”不超過150個字符”/>       頁面描述
 <meta name=”keywords” content=””/>      頁面關鍵詞者
 <meta name=”author” content=”name, [email protected]”/>    網頁作
 <meta name=”robots” content=”index,follow”/>      搜索引擎抓取
 <meta name=”viewport” content=”initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no”> 爲移動設備添加 viewport
 <meta name=”apple-mobile-web-app-title” content=”標題”> iOS 設備 begin
 <meta name=”apple-mobile-web-app-capable” content=”yes”/>  添加到主屏後的標題(iOS 6 新增)
 是否啓用 WebApp 全屏模式,刪除蘋果默認的工具欄和菜單欄
 <meta name=”apple-itunes-app” content=”app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL”>
 添加智能 App 廣告條 Smart App Banner(iOS 6+ Safari)
 <meta name=”apple-mobile-web-app-status-bar-style” content=”black”/>
 <meta name=”format-detection” content=”telphone=no, email=no”/>  設置蘋果工具欄顏色
 <meta name=”renderer” content=”webkit”>  啓用360瀏覽器的極速模式(webkit)
 <meta http-equiv=”X-UA-Compatible” content=”IE=edge”>     避免IE使用兼容模式
 <meta http-equiv=”Cache-Control” content=”no-siteapp” />    不讓百度轉碼
 <meta name=”HandheldFriendly” content=”true”>     針對手持設備優化,主要是針對一些老的不識別viewport的瀏覽器,比如黑莓
 <meta name=”MobileOptimized” content=”320″>   微軟的老式瀏覽器
 <meta name=”screen-orientation” content=”portrait”>   uc強制豎屏
 <meta name=”x5-orientation” content=”portrait”>    QQ強制豎屏
 <meta name=”full-screen” content=”yes”>              UC強制全屏
 <meta name=”x5-fullscreen” content=”true”>       QQ強制全屏
 <meta name=”browsermode” content=”application”>   UC應用模式
 <meta name=”x5-page-mode” content=”app”>    QQ應用模式
 <meta name=”msapplication-tap-highlight” content=”no”>    windows phone 點擊無高光
 設置頁面不緩存
 <meta http-equiv=”pragma” content=”no-cache”>
 <meta http-equiv=”cache-control” content=”no-cache”>
 <meta http-equiv=”expires” content=”0″>

詳細資料可以參考: 《Meta 標籤用法大全》

57. css reset 和 normalize.css 有什麼區別?

相關知識點:

 爲什麼會有 CSS Reset 的存在呢?那是因爲早期的瀏覽器支持和理解的 CSS 規範不同,導致渲染頁面時效果不一致,會出現很多
 兼容性問題。

 reset 的目的,是將所有的瀏覽器的自帶樣式重置掉,這樣更易於保持各瀏覽器渲染的一致性。

 normalize 的理念則是儘量保留瀏覽器的默認樣式,不進行太多的重置,而盡力讓這些樣式保持一致並儘可能與現代標準相符合。


 1.Normalize.css 保護了有價值的默認值

 Reset 通過爲幾乎所有的元素施加默認樣式,強行使得元素有相同的視覺效果。 相比之下,Normalize.css 保持了許多默認的瀏
 覽器樣式。 這就意味着你不用再爲所有公共的排版元素重新設置樣式。 當一個元素在不同的瀏覽器中有不同的默認值時,Normali
 ze.css 會力求讓這些樣式保持一致並儘可能與現代標準相符合。


 2.Normalize.css 修復了瀏覽器的 bug

 它修復了常見的桌面端和移動端瀏覽器的 bug。這往往超出了 Reset 所能做到的範疇。關於這一點,Normalize.css 修復的問題
 包含了 HTML5 元素的顯示設置、預格式化文字的 font-size 問題、在 IE9 中 SVG 的溢出、許多出現在各瀏覽器和操作系統中
 的與表單相關的 bug。


 3.Normalize.css 沒有複雜的繼承鏈

 使用 Reset 最讓人困擾的地方莫過於在瀏覽器調試工具中大段大段的繼承鏈。在 Normalize.css 中就不會有這樣的問題,因爲在
 我們的準則中對多選擇器的使用時非常謹慎的,我們僅會有目的地對目標元素設置樣式。


 4.Normalize.css 是模塊化的

 這個項目已經被拆分爲多個相關卻又獨立的部分,這使得你能夠很容易也很清楚地知道哪些元素被設置了特定的值。因此這能讓你自己
 選擇性地移除掉某些永遠不會用到部分(比如表單的一般化)。


 5.Normalize.css 擁有詳細的文檔

 Normalize.css 的代碼基於詳細而全面的跨瀏覽器研究與測試。這個文件中擁有詳細的代碼說明並在 Github Wiki 中有進一步的
 說明。這意味着你可以找到每一行代碼具體完成了什麼工作、爲什麼要寫這句代碼、瀏覽器之間的差異,並且你可以更容易地進行自己
 的測試。

回答:

 css reset 是最早的一種解決瀏覽器間樣式不兼容問題的方案,它的基本思想是將瀏覽器的所有樣式都重置掉,從而達到所有瀏覽器
 樣式保持一致的效果。但是使用這種方法,可能會帶來一些性能上的問題,並且對於一些元素的不必要的樣式的重置,其實反而會造成
 畫蛇添足的效果。

 後面出現一種更好的解決瀏覽器間樣式不兼容的方法,就是 normalize.css ,它的思想是儘量的保留瀏覽器自帶的樣式,通過在原
 有的樣式的基礎上進行調整,來保持各個瀏覽器間的樣式表現一致。相對與 css reset,normalize.css 的方法保留了有價值的默
 認值,並且修復了一些瀏覽器的 bug,而且使用 normalize.css 不會造成元素複雜的繼承鏈。

詳細資料可以參考: 《關於CSS Reset 那些事(一)之 歷史演變與 Normalize.css》 《Normalize.css 和 Reset CSS 有什麼本質區別沒?》

58. 用於預格式化文本的標籤是?

 預格式化就是保留文字在源碼中的格式 最後顯示出來樣式與源碼中的樣式一致 所見即所得。

 <pre> 定義預格式文本,保持文本原有的格式

59. DHTML 是什麼?

 DHTML 將 HTML、JavaScript、DOM 以及 CSS 組合在一起,用於創造動態性更強的網頁。通過 JavaScript 和 HTML DOM,能
 夠動態地改變 HTML 元素的樣式。

 DHTML 實現了網頁從 Web 服務器下載後無需再經過服務的處理,而在瀏覽器中直接動態地更新網頁的內容、排版樣式和動畫的功
 能。例如,當鼠標指針移到文章段落中時,段落能夠變成藍色,或者當鼠標指針移到一個超級鏈接上時,會自動生成一個下拉式子鏈
 接目錄等。

 包括:
 (1)動態內容(Dynamic Content):動態地更新網頁內容,可“動態”地插入、修改或刪除網頁的元件,如文字、圖像、標記等。

 (2)動態排版樣式(Dynamic Style Sheets):W3C 的 CSS 樣式表提供了設定 HTML 標記的字體大小、字形、樣式、粗細、
     文字顏色、行高度、加底線或加中間橫線、縮排、與邊緣距離、靠左右或置中、背景圖片或顏色等排版功能,而“動態排版樣
     式”即可以“動態”地改變排版樣式。

60. head 標籤中必不少的是?

 <head> 標籤用於定義文檔的頭部,它是所有頭部元素的容器。<head> 中的元素可以引用腳本、指示瀏覽器在哪裏找到樣式表、提供
 元信息等等。

 文檔的頭部描述了文檔的各種屬性和信息,包括文檔的標題、在 Web 中的位置以及和其他文檔的關係等。絕大多數文檔頭部包含的數
 據都不會真正作爲內容顯示給讀者。

 下面這些標籤可用在 head 部分:<base>, <link>, <meta>, <script>, <style>, 以及 <title>。

 <title> 定義文檔的標題,它是 head 部分中唯一必需的元素。

61. HTML5 新增的表單元素有?

 datalist 規定輸入域的選項列表,通過 option 創建! 
 
 keygen 提供一種驗證用戶的可靠方法,密鑰對生成器,私鑰存於客戶端,公鑰發到服務器,用於之後驗證客戶端證書!
 
 output 元素用於不同類型的輸出!

62. 在 HTML5 中,哪個方法用於獲得用戶的當前位置?

 getCurrentPosition()

63. 文檔的不同註釋方式?

 HTML 的註釋方法 <!--註釋內容--> 
 
 CSS 的��釋方法 /*註釋內容*/ 
 
 JavaScript 的註釋方法 /* 多行註釋方式 */ //單行註釋方式

64. disabled 和 readonly 的區別?

 disabled 指當 input 元素加載時禁用此元素。input 內容不會隨着表單提交。
  
 readonly 規定輸入字段爲只讀。input 內容會隨着表單提交。

 無論設置 readonly 還是 disabled,通過 js 腳本都能更改 input 的 value

65. 主流瀏覽器內核私有屬性 css 前綴?

 mozilla 內核 (irefox,flock 等)    -moz
 webkit  內核 (safari,chrome 等)   -webkit
 opera   內核 (opera 瀏覽器)        -o
 trident 內核 (ie 瀏覽器)           -ms

66. 前端性能優化?

 前端性能優化主要是爲了提高頁面的加載速度,優化用戶的訪問體驗。我認爲可以從這些方面來進行優化。

 第一個方面是頁面的內容方面

 (1)通過文件合併、css 雪碧圖、使用 base64 等方式來減少 HTTP 請求數,避免過多的請求造成等待的情況。

 (2)通過 DNS 緩存等機制來減少 DNS 的查詢次數。

 (3)通過設置緩存策略,對常用不變的資源進行緩存。

 (4)使用延遲加載的方式,來減少頁面首屏加載時需要請求的資源。延遲加載的資源當用戶需要訪問時,再去請求加載。

 (5)通過用戶行爲,對某些資源使用預加載的方式,來提高用戶需要訪問資源時的響應速度。

 第二個方面是服務器方面

 (1)使用 CDN 服務,來提高用戶對於資源請求時的響應速度。

 (2)服務器端啓用 Gzip、Deflate 等方式對於傳輸的資源進行壓縮,減小文件的體積。

 (3)儘可能減小 cookie 的大小,並且通過將靜態資源分配到其他域名下,來避免對靜態資源請求時攜帶不必要的 cookie

 第三個方面是 CSS 和 JavaScript 方面

 (1)把樣式表放在頁面的 head 標籤中,減少頁面的首次渲染的時間。

 (2)避免使用 @import 標籤。

 (3)儘量把 js 腳本放在頁面底部或者使用 defer 或 async 屬性,避免腳本的加載和執行阻塞頁面的渲染。

 (4)通過對 JavaScript 和 CSS 的文件進行壓縮,來減小文件的體積。

詳細的資料可以參考: 《前端性能優化之雅虎35條軍規》 《你真的瞭解 gzip 嗎?》 《前端性能優化之 gzip》

67. Chrome 中的 Waterfall ?

詳細資料可以參考: 《前端性能之 Chrome 的 Waterfall》 《教你讀懂網絡請求的瀑布圖》 《前端妹子跟我抱怨她們的頁面加載很慢的時候,如何在她面前優雅地裝逼?》

68. 掃描二維碼登錄網頁是什麼原理,前後兩個事件是如何聯繫的?

 核心過程應該是:瀏覽器獲得一個臨時 id,通過長連接等待客戶端掃描帶有此 id 的二維碼後,從長連接中獲得客戶端上報給 serv
 er的帳號信息進行展示。並在客戶端點擊確認後,獲得服務器授信的令牌,進行隨後的信息交互過程。在超時、網絡斷開、其他設備
 上登錄後,此前獲得的令牌或丟失、或失效,對授權過程形成有效的安全防護。

 我的理解

 二維碼登錄網頁的基本原理是,用戶進入登錄網頁後,服務器生成一個 uid 來標識一個用戶。對應的二維碼對應了一個對應 uid 
 的鏈接,任何能夠識別二維碼的應用都可以獲得這個鏈接,但是它們沒有辦法和對應登錄的服務器響應。比如微信的二維碼登錄,只
 有用微信識這個二維碼纔有效。當微信客戶端打開這個鏈接時,對應的登錄服務器就獲得了用戶的相關信息。這個時候登錄網頁根據
 先前的長連接獲取到服務器傳過來的用戶信息進行顯示。然後提前預加載一些登錄後可能用到的信息。當客戶端點擊確認授權登陸後,
 服務器生成一個權限令牌給網頁,網頁之後使用這個令牌進行信息的交互過程。由於整個授權的過程都是在手機端進行的,因此能夠
 很好的防止 PC 上氾濫的病毒。並且在超時、網絡斷開、其他設備上登錄後,此前獲得的令牌或丟失、或失效,對授權過程能夠形成
 有效的安全防護。

CSS 面試知識點總結

本部分主要是筆者在複習 CSS 相關知識和一些相關面試題時所做的筆記,如果出現錯誤,希望大家指出!

目錄

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

相關知識點:

(1)有兩種盒子模型:IE盒模型(border-box)、W3C標準盒模型(content-box)
(2)盒模型:分爲內容(content)、填充(padding)、邊界(margin)、邊框(border)四個部分

IE盒模型和W3C標準盒模型的區別:

(1)W3C標準盒模型:屬性width,height只包含內容content,不包含border和padding
(2)IE盒模型:屬性width,height包含content、border和padding,指的是content
+padding+border。

在ie8+瀏覽器中使用哪個盒模型可以由box-sizing(CSS新增的屬性)控制,默認值爲content-box,即標準盒模型;
如果將box-sizing設爲border-box則用的是IE盒模型。如果在ie6,7,8中DOCTYPE缺失會將盒子模型解釋爲IE
盒子模型。若在頁面中聲明瞭DOCTYPE類型,所有的瀏覽器都會把盒模型解釋爲W3C盒模型。

回答:

盒模型都是由四個部分組成的,分別是margin、border、padding和content。

標準盒模型和IE盒模型的區別在於設置width和height時,所對應的範圍不同。標準盒模型的width和height屬性的
範圍只包含了content,而IE盒模型的width和height屬性的範圍包含了border、padding和content。

一般來說,我們可以通過修改元素的box-sizing屬性來改變元素的盒模型。

詳細的資料可以參考: 《CSS 盒模型詳解》

2.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)通配符選擇器(*)

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

相關知識點:

單冒號(:)用於CSS3僞類,雙冒號(::)用於CSS3僞元素。(僞元素由雙冒號和僞元素名稱組成)
雙冒號是在當前規範中引入的,用於區分僞類和僞元素。不過瀏覽器需要同時支持舊的已經存在的僞元素寫法,
比如:first-line、:first-letter、:before、:after等,
而新的在CSS3中引入的僞元素則不允許再支持舊的單冒號的寫法。

想讓插入的內容出現在其它內容前,使用::before,否者,使用::after;
在代碼順序上,::after生成的內容也比::before生成的內容靠後。
如果按堆棧視角,::after生成的內容會在::before生成的內容之上。

回答:

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

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

4.僞類與僞元素的區別

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

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

僞元素用於創建一些不在文檔樹中的元素,併爲其添加樣式。它們允許我們爲元素的某些部分設置樣式。比如說,我們可以通過::be
fore來在一個元素前增加一些文本,併爲這些文本添加樣式。雖然用戶可以看到這些文本,但是這些文本實際上不在文檔樹中。

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

詳細資料可以參考: 《總結僞類與僞元素》

5.CSS 中哪些屬性可以繼承?

相關資料:

每個CSS屬性定義的概述都指出了這個屬性是默認繼承的,還是默認不繼承的。這決定了當你沒有爲元素的屬性指定值時該如何計算
值。

當元素的一個繼承屬性沒有指定值時,則取父元素的同屬性的計算值。只有文檔根元素取該屬性的概述中給定的初始值(這裏的意思應
該是在該屬性本身的定義中的默認值)。

當元素的一個非繼承屬性(在Mozillacode裏有時稱之爲resetproperty)沒有指定值時,則取屬性的初始值initialv
alue(該值在該屬性的概述裏被指定)。

有繼承性的屬性:

(1)字體系列屬性
font、font-family、font-weight、font-size、font-style、font-variant、font-stretch、font-size-adjust

(2)文本系列屬性
text-indent、text-align、text-shadow、line-height、word-spacing、letter-spacing、
text-transform、direction、color

(3)表格佈局屬性
caption-sideborder-collapseempty-cells

(4)列表屬性
list-style-type、list-style-image、list-style-position、list-style

(5)光標屬性
cursor

(6)元素可見性
visibility

(7)還有一些不常用的;speak,page,設置嵌套引用的引號類型quotes等屬性


注意:當一個屬性不是繼承屬性時,可以使用inherit關鍵字指定一個屬性應從父元素繼承它的值,inherit關鍵字用於顯式地
指定繼承性,可用於任何繼承性/非繼承性屬性。

回答:

每一個屬性在定義中都給出了這個屬性是否具有繼承性,一個具有繼承性的屬性會在沒有指定值的時候,會使用父元素的同屬性的值
來作爲自己的值。

一般具有繼承性的屬性有,字體相關的屬性,font-size和font-weight等。文本相關的屬性,color和text-align等。
表格的一些佈局屬性、列表屬性如list-style等。還有光標屬性cursor、元素可見性visibility。

當一個屬性不是繼承屬性的時候,我們也可以通過將它的值設置爲inherit來使它從父元素那獲取同名的屬性值來繼承。

詳細的資料可以參考: 《繼承屬性》 《CSS 有哪些屬性可以繼承?》

6.CSS 優先級算法如何計算?

相關知識點:

CSS的優先級是根據樣式聲明的特殊性值來判斷的。

選擇器的特殊性值分爲四個等級,如下:

(1)標籤內選擇符x,0,0,0
(2)ID選擇符0,x,0,0
(3)class選擇符/屬性選擇符/僞類選擇符	0,0,x,0
(4)元素和僞元素選擇符0,0,0,x

計算方法:

(1)每個等級的初始值爲0
(2)每個等級的疊加爲選擇器出現的次數相加
(3)不可進位,比如0,99,99,99
(4)依次表示爲:0,0,0,0
(5)每個等級計數之間沒關聯
(6)等級判斷從左向右,如果某一位數值相同,則判斷下一位數值
(7)如果兩個優先級相同,則最後出現的優先級高,!important也適用
(8)通配符選擇器的特殊性值爲:0,0,0,0
(9)繼承樣式優先級最低,通配符樣式優先級高於繼承樣式
(10)!important(權重),它沒有特殊性值,但它的優先級是最高的,爲了方便記憶,可以認爲它的特殊性值爲1,0,0,0,0。

計算實例:

(1)#demoa{color:orange;}/*特殊性值:0,1,0,1*/
(2)div#demoa{color:red;}/*特殊性值:0,1,0,2*/


注意:
(1)樣式應用時,css會先查看規則的權重(!important),加了權重的優先級最高,當權重相同的時候,會比較規則的特殊性。

(2)特殊性值越大的聲明優先級越高。

(3)相同特殊性值的聲明,根據樣式引入的順序,後聲明的規則優先級高(距離元素出現最近的)

回答:

判斷優先級時,首先我們會判斷一條屬性聲明是否有權重,也就是是否在聲明後面加上了!important。一條聲明如果加上了權重,
那麼它的優先級就是最高的,前提是它之後不再出現相同權重的聲明。如果權重相同,我們則需要去比較匹配規則的特殊性。

一條匹配規則一般由多個選擇器組成,一條規則的特殊性由組成它的選擇器的特殊性累加而成。選擇器的特殊性可以分爲四個等級,
第一個等級是行內樣式,爲1000,第二個等級是id選擇器,爲0100,第三個等級是類選擇器、僞類選擇器和屬性選擇器,爲0010,
第四個等級是元素選擇器和僞元素選擇器,爲0001。規則中每出現一個選擇器,就將它的特殊性進行疊加,這個疊加只限於對應的等
級的疊加,不會產生進位。選擇器特殊性值的比較是從左向右排序的,也就是說以1開頭的特殊性值比所有以0開頭的特殊性值要大。
比如說特殊性值爲1000的的規則優先級就要比特殊性值爲0999的規則高。如果兩個規則的特殊性值相等的時候,那麼就會根據它們引
入的順序,後出現的規則的優先級最高。

對於組合聲明的特殊性值計算可以參考: 《CSS 優先級計算及應用》 《CSS 優先級計算規則》

7.關於僞類 LVHA 的解釋?

a標籤有四種狀態:鏈接訪問前、鏈接訪問後、鼠標滑過、激活,分別對應四種僞類:link、:visited、:hover、:active;

當鏈接未訪問過時:

(1)當鼠標滑過a鏈接時,滿足:link和:hover兩種狀態,要改變a標籤的顏色,就必須將:hover僞類在:link僞
類後面聲明;
(2)當鼠標點擊激活a鏈接時,同時滿足:link、:hover、:active三種狀態,要顯示a標籤激活時的樣式(:active),
必須將:active聲明放到:link和:hover之後。因此得出LVHA這個順序。

當鏈接訪問過時,情況基本同上,只不過需要將:link換成:visited。

這個順序能不能變?可以,但也只有:link和:visited可以交換位置,因爲一個鏈接要麼訪問過要麼沒訪問過,不可能同時滿足,
也就不存在覆蓋的問題。

8.CSS3 新增僞類有那些?

(1)elem:nth-child(n)選中父元素下的第n個子元素,並且這個子元素的標籤名爲elem,n可以接受具體的數
值,也可以接受函數。

(2)elem:nth-last-child(n)作用同上,不過是從後開始查找。

(3)elem:last-child選中最後一個子元素。

(4)elem:only-child如果elem是父元素下唯一的子元素,則選中之。

(5)elem:nth-of-type(n)選中父元素下第n個elem類型元素,n可以接受具體的數值,也可以接受函數。

(6)elem:first-of-type選中父元素下第一個elem類型元素。

(7)elem:last-of-type選中父元素下最後一個elem類型元素。

(8)elem:only-of-type如果父元素下的子元素只有一個elem類型元素,則選中該元素。

(9)elem:empty選中不包含子元素和內容的elem類型元素。

(10)elem:target選擇當前活動的elem元素。

(11):not(elem)選擇非elem元素的每個元素。

(12):enabled	控制表單控件的禁用狀態。

(13):disabled		控制表單控件的禁用狀態。

(14):checked單選框或複選框被選中。

詳細的資料可以參考: 《CSS3 新特性總結(僞類)》 《淺談 CSS 僞類和僞元素及 CSS3 新增僞類》

9.如何居中 div?

-水平居中:給 div 設置一個寬度,然後添加 margin:0auto 屬性

div {
  width: 200px;
  margin: 0auto;
}

-水平居中,利用 text-align:center 實現

.container {
  background: rgba(0, 0, 0, 0.5);
  text-align: center;
  font-size: 0;
}

.box {
  display: inline-block;
  width: 500px;
  height: 400px;
  background-color: pink;
}

-讓絕對定位的 div 居中

div {
  position: absolute;
  width: 300px;
  height: 300px;
  margin: auto;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background-color: pink; /*方便看效果*/
}

-水平垂直居中一

/*確定容器的寬高寬500高300的層設置層的外邊距div{*/
position:absolute;/*絕對定位*/
width:500px;
height:300px;
top:50%;
left:50%;
margin:-150px00-250px;/*外邊距爲自身寬高的一半*/
background-color:pink;/*方便看效果*/
}

-水平垂直居中二

/*未知容器的寬高,利用`transform`屬性*/
div {
  position: absolute; /*相對定位或絕對定位均可*/
  width: 500px;
  height: 300px;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: pink; /*方便看效果*/
}

-水平垂直居中三

/*利用flex佈局實際使用時應考慮兼容性*/
.container {
  display: flex;
  align-items: center; /*垂直居中*/
  justify-content: center; /*水平居中*/
}
.containerdiv {
  width: 100px;
  height: 100px;
  background-color: pink; /*方便看效果*/
}

-水平垂直居中四

/*利用text-align:center和vertical-align:middle屬性*/
.container {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.5);
  text-align: center;
  font-size: 0;
  white-space: nowrap;
  overflow: auto;
}

.container::after {
  content: "";
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}

.box {
  display: inline-block;
  width: 500px;
  height: 400px;
  background-color: pink;
  white-space: normal;
  vertical-align: middle;
}

回答:

一般常見的幾種居中的方法有:

對於寬高固定的元素

(1)我們可以利用margin:0auto來實現元素的水平居中。

(2)利用絕對定位,設置四個方向的值都爲0,並將margin設置爲auto,由於寬高固定,因此對應方向實現平分,可以實現水
平和垂直方向上的居中。

(3)利用絕對定位,先將元素的左上角通過top:50%和left:50%定位到頁面的中心,然後再通過margin負值來調整元素
的中心點到頁面的中心。

(4)利用絕對定位,先將元素的左上角通過top:50%和left:50%定位到頁面的中心,然後再通過translate來調整元素
的中心點到頁面的中心。

(5)使用flex佈局,通過align-items:center和justify-content:center設置容器的垂直和水平方向上爲居中對
齊,然後它的子元素也可以實現垂直和水平的居中。

對於寬高不定的元素,上面的後面兩種方法,可以實現元素的垂直和水平的居中。

10.display 有哪些值?說明他們的作用。

block	塊類型。默認寬度爲父元素寬度,可設置寬高,換行顯示。
none	元素不顯示,並從文檔流中移除。
inline	行內元素類型。默認寬度爲內容寬度,不可設置寬高,同行顯示。
inline-block默認寬度爲內容寬度,可以設置寬高,同行顯示。
list-item	像塊類型元素一樣顯示,並添加樣式列表標記。
table	此元素會作爲塊級表格來顯示。
inherit	規定應該從父元素繼承display屬性的值。

詳細資料可以參考: 《CSSdisplay 屬性》

11.position 的值 relative 和 absolute 定位原點是?

相關知識點:

absolute
生成絕對定位的元素,相對於值不爲static的第一個父元素的paddingbox進行定位,也可以理解爲離自己這一級元素最近的
一級position設置爲absolute或者relative的父元素的paddingbox的左上角爲原點的。

fixed(老IE不支持)
生成絕對定位的元素,相對於瀏覽器窗口進行定位。

relative
生成相對定位的元素,相對於其元素本身所在正常位置進行定位。

static
默認值。沒有定位,元素出現在正常的流中(忽略top,bottom,left,right,z-index聲明)。

inherit
規定從父元素繼承position屬性的值。

回答:

relative定位的元素,是相對於元素本身的正常位置來進行定位的。

absolute定位的元素,是相對於它的第一個position值不爲static的祖先元素的paddingbox來進行定位的。這句話
我們可以這樣來理解,我們首先需要找到絕對定位元素的一個position的值不爲static的祖先元素,然後相對於這個祖先元
素的paddingbox來定位,也就是說在計算定位距離的時候,padding的值也要算進去。

12.CSS3 有哪些新特性?(根據項目回答)

新增各種CSS選擇器	(:not(.input):所有class不是“input”的節點)
圓角		(border-radius:8px)
多列布局	(multi-columnlayout)
陰影和反射	(Shadow\Reflect)
文字特效		(text-shadow)
文字渲染		(Text-decoration)
線性漸變		(gradient)
旋轉			(transform)
縮放,定位,傾斜,動畫,多背景
例如:transform:\scale(0.85,0.90)\translate(0px,-30px)\skew(-9deg,0deg)\Animation:

13.請解釋一下 CSS3 的 Flexbox(彈性盒佈局模型),以及適用場景?

相關知識點:

Flex是FlexibleBox的縮寫,意爲"彈性佈局",用來爲盒狀模型提供最大的靈活性。

任何一個容器都可以指定爲Flex佈局。行內元素也可以使用Flex佈局。注意,設爲Flex佈局以後,子元素的float、cl
ear和vertical-align屬性將失效。

採用Flex佈局的元素,稱爲Flex容器(flexcontainer),簡稱"容器"。它的所有子元素自動成爲容器成員,稱爲Flex
項目(flexitem),簡稱"項目"。

容器默認存在兩根軸:水平的主軸(mainaxis)和垂直的交叉軸(crossaxis),項目默認沿主軸排列。


以下6個屬性設置在容器上。

flex-direction屬性決定主軸的方向(即項目的排列方向)。

flex-wrap屬性定義,如果一條軸線排不下,如何換行。

flex-flow屬性是flex-direction屬性和flex-wrap屬性的簡寫形式,默認值爲rownowrap。

justify-content屬性定義了項目在主軸上的對齊方式。

align-items屬性定義項目在交叉軸上如何對齊。

align-content屬性定義了多根軸線的對齊方式。如果項目只有一根軸線,該屬性不起作用。


以下6個屬性設置在項目上。

order屬性定義項目的排列順序。數值越小,排列越靠前,默認爲0。

flex-grow屬性定義項目的放大比例,默認爲0,即如果存在剩餘空間,也不放大。

flex-shrink屬性定義了項目的縮小比例,默認爲1,即如果空間不足,該項目將縮小。

flex-basis屬性定義了在分配多餘空間之前,項目佔據的主軸空間。瀏覽器根據這個屬性,計算主軸是否有多餘空間。它的默認
值爲auto,即項目的本來大小。

flex屬性是flex-grow,flex-shrink和flex-basis的簡寫,默認值爲01auto。

align-self屬性允許單個項目有與其他項目不一樣的對齊方式,可覆蓋align-items屬性。默認值爲auto,表示繼承父
元素的align-items屬性,如果沒有父元素,則等同於stretch。

回答:

flex佈局是CSS3新增的一種佈局方式,我們可以通過將一個元素的display屬性值設置爲flex從而使它成爲一個flex
容器,它的所有子元素都會成爲它的項目。

一個容器默認有兩條軸,一個是水平的主軸,一個是與主軸垂直的交叉軸。我們可以使用flex-direction來指定主軸的方向。
我們可以使用justify-content來指定元素在主軸上的排列方式,使用align-items來指定元素在交叉軸上的排列方式。還
可以使用flex-wrap來規定當一行排列不下時的換行方式。

對於容器中的項目,我們可以使用order屬性來指定項目的排列順序,還可以使用flex-grow來指定當排列空間有剩餘的時候,
項目的放大比例。還可以使用flex-shrink來指定當排列空間不足時,項目的縮小比例。

詳細資料可以參考: 《Flex 佈局教程:語法篇》 《Flex 佈局教程:實例篇》

14.用純 CSS 創建一個三角形的原理是什麼?

採用的是相鄰邊框連接處的均分原理。
  將元素的寬高設爲0,只設置
  border
  ,把任意三條邊隱藏掉(顏色設爲
  transparent),剩下的就是一個三角形。
  #demo {
  width: 0;
  height: 0;
  border-width: 20px;
  border-style: solid;
  border-color: transparenttransparentredtransparent;
}

15.一個滿屏品字佈局如何設計?

簡單的方式:
	上面的div寬100%,
	下面的兩個div分別寬50%,
	然後用float或者inline使其不換行即可

16.CSS 多列等高如何實現?

(1)利用padding-bottom|margin-bottom正負值相抵,不會影響頁面佈局的特點。設置父容器設置超出隱藏(overflow:
hidden),這樣父容器的高度就還是它裏面的列沒有設定padding-bottom時的高度,當它裏面的任一列高度增加了,則
父容器的高度被撐到裏面最高那列的高度,其他比這列矮的列會用它們的padding-bottom補償這部分高度差。

(2)利用table-cell所有單元格高度都相等的特性,來實現多列等高。

(3)利用flex佈局中項目align-items屬性默認爲stretch,如果項目未設置高度或設爲auto,將佔滿整個容器的高度
的特性,來實現多列等高。

詳細資料可以參考: 《前端應該掌握的 CSS 實現多列等高佈局》 《CSS:多列等高佈局》

17.經常遇到的瀏覽器的兼容性有哪些?原因,解決方法是什麼,常用 hack 的技巧?

(1)png24位的圖片在iE6瀏覽器上出現背景
解決方案:做成PNG8,也可以引用一段腳本處理。

(2)瀏覽器默認的margin和padding不同
解決方案:加一個全局的*{margin:0;padding:0;}來統一。

(3)IE6雙邊距bug:在IE6下,如果對元素設置了浮動,同時又設置了margin-left或
margin-right,margin值會加倍。

#box{float:left;width:10px;margin:00010px;}

這種情況之下IE會產生20px的距離
解決方案:在float的標籤樣式控制中加入_display:inline;將其轉化爲行內屬性。(_這個符號只有ie6會識別)

(4)漸進識別的方式,從總體中逐漸排除局部。
首先,巧妙的使用"\9"這一標記,將IE遊覽器從所有情況中分離出來。
接着,再次使用"+"將IE8和IE7、IE6分離開來,這樣IE8已經獨立識別。
.bb{
background-color:#f1ee18;/*所有識別*/
.background-color:#00deff\9;/*IE6、7、8識別*/
+background-color:#a200ff;/*IE6、7識別*/
_background-color:#1e0bd1;/*IE6識別*/
}

(5)IE下,可以使用獲取常規屬性的方法來獲取自定義屬性,也可以使用getAttribute()獲取自定義
屬性;Firefox下,只能使用getAttribute()獲取自定義屬性
解決方法:統一通過getAttribute()獲取自定義屬性。

(6)IE下,event對象有x、y屬性,但是沒有pageX、pageY屬性;Firefox下,event對象有
pageX、pageY屬性,但是沒有x、y屬性。
解決方法:(條件註釋)缺點是在IE瀏覽器下可能會增加額外的HTTP請求數。

(7)Chrome中文界面下默認會將小於12px的文本強制按照12px顯示
解決方法:

1.可通過加入CSS屬性-webkit-text-size-adjust:none;解決。但是,在chrome
更新到27版本之後就不可以用了。

2.還可以使用-webkit-transform:scale(0.5);注意-webkit-transform:scale(0.75);
收縮的是整個span的大小,這時候,必須要將span轉換成塊元素,可以使用display:block/inline-block/...;

(8)超鏈接訪問過後hover樣式就不出現了,被點擊訪問過的超鏈接樣式不再具有hover和active了
解決方法:改變CSS屬性的排列順序L-V-H-A

(9)怪異模式問題:漏寫DTD聲明,Firefox仍然會按照標準模式來解析網頁,但在IE中會觸發怪異模
式。爲避免怪異模式給我們帶來不必要的麻煩,最好養成書寫DTD聲明的好習慣。

18.li 與 li 之間有看不見的空白間隔是什麼原因引起的?有什麼解決辦法?

瀏覽器會把inline元素間的空白字符(空格、換行、Tab等)渲染成一個空格。而爲了美觀。我們通常是一個<li>放在一行,
這導致<li>換行後產生換行字符,它變成一個空格,佔用了一個字符的寬度。

解決辦法:

(1)爲<li>設置float:left。不足:有些容器是不能設置浮動,如左右切換的焦點圖等。

(2)將所有<li>寫在同一行。不足:代碼不美觀。

(3)將<ul>內的字符尺寸直接設爲0,即font-size:0。不足:<ul>中的其他字符尺寸也被設爲0,需要額外重新設定其他
字符尺寸,且在Safari瀏覽器依然會出現空白間隔。

(4)消除<ul>的字符間隔letter-spacing:-8px,不足:這也設置了<li>內的字符間隔,因此需要將<li>內的字符
間隔設爲默認letter-spacing:normal。

詳細資料可以參考: 《li 與 li 之間有看不見的空白間隔是什麼原因引起的?》

19.爲什麼要初始化 CSS 樣式?

-因爲瀏覽器的兼容問題,不同瀏覽器對有些標籤的默認值是不同的,如果沒對CSS初始化往往會出現瀏覽器之間的頁面顯示差異。

-當然,初始化樣式會對SEO有一定的影響,但魚和熊掌不可兼得,但力求影響最小的情況下初始化。

最簡單的初始化方法:*{padding:0;margin:0;}(強烈不建議)

淘寶的樣式初始化代碼:
body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend
,button,input,textarea,th,td{margin:0;padding:0;}
body,button,input,select,textarea{font:12px/1.5tahoma,arial,\5b8b\4f53;}
h1,h2,h3,h4,h5,h6{font-size:100%;}
address,cite,dfn,em,var{font-style:normal;}
code,kbd,pre,samp{font-family:couriernew,courier,monospace;}
small{font-size:12px;}
ul,ol{list-style:none;}
a{text-decoration:none;}
a:hover{text-decoration:underline;}
sup{vertical-align:text-top;}
sub{vertical-align:text-bottom;}
legend{color:#000;}
fieldset,img{border:0;}
button,input,select,textarea{font-size:100%;}
table{border-collapse:collapse;border-spacing:0;}

20.什麼是包含塊,對於包含塊的理解?

包含塊(containingblock)就是元素用來計算和定位的一個框。

(1)根元素(很多場景下可以看成是<html>)被稱爲“初始包含塊”,其尺寸等同於瀏覽器可視窗口的大小。

(2)對於其他元素,如果該元素的position是relative或者static,則“包含塊”由其最近的塊容器祖先盒的contentbox
邊界形成。

(3)如果元素position:fixed,則“包含塊”是“初始包含塊”。

(4)如果元素position:absolute,則“包含塊”由最近的position不爲static的祖先元素建立,具體方式如下:

如果該祖先元素是純inline元素,則規則略複雜:
•假設給內聯元素的前後各生成一個寬度爲0的內聯盒子(inlinebox),則這兩個內聯盒子的paddingbox外面的包
圍盒就是內聯元素的“包含塊”;
•如果該內聯元素被跨行分割了,那麼“包含塊”是未定義的,也就是CSS2.1規範並沒有明確定義,瀏覽器自行發揮
否則,“包含塊”由該祖先的paddingbox邊界形成。

如果沒有符合條件的祖先元素,則“包含塊”是“初始包含塊”。

21.CSS 裏的 visibility 屬性有個 collapse 屬性值是幹嘛用的?在不同瀏覽器下以後什麼區別?

(1)對於一般的元素,它的表現跟visibility:hidden;是一樣的。元素是不可見的,但此時仍佔用頁面空間。

(2)但例外的是,如果這個元素是table相關的元素,例如table行,tablegroup,table列,tablecolumngroup,它的
表現卻跟display:none一樣,也就是說,它們佔用的空間也會釋放。

在不同瀏覽器下的區別:

在谷歌瀏覽器裏,使用collapse值和使用hidden值沒有什麼區別。

在火狐瀏覽器、Opera和IE11裏,使用collapse值的效果就如它的字面意思:table的行會消失,它的下面一行會補充它的位
置。

詳細資料可以參考: 《CSS 裏的 visibility 屬性有個鮮爲人知的屬性值:collapse》

22.width:auto 和 width:100%的區別

一般而言

width:100%會使元素box的寬度等於父元素的contentbox的寬度。

width:auto會使元素撐滿整個父元素,margin、border、padding、content區域會自動分配水平空間。

23.絕對定位元素與非絕對定位元素的百分比計算的區別

絕對定位元素的寬高百分比是相對於臨近的position不爲static的祖先元素的paddingbox來計算的。

非絕對定位元素的寬高百分比則是相對於父元素的contentbox來計算的。

24.簡單介紹使用圖片 base64 編碼的優點和缺點。

base64編碼是一種圖片處理格式,通過特定的算法將圖片編碼成一長串字符串,在頁面上顯示的時候,可以用該字符串來代替圖片的
url屬性。

使用base64的優點是:

(1)減少一個圖片的HTTP請求

使用base64的缺點是:

(1)根據base64的編碼原理,編碼後的大小會比原文件大小大1/3,如果把大圖片編碼到html/css中,不僅會造成文件體
積的增加,影響文件的加載速度,還會增加瀏覽器對html或css文件解析渲染的時間。

(2)使用base64無法直接緩存,要緩存只能緩存包含base64的文件,比如HTML或者CSS,這相比域直接緩存圖片的效果要
差很多。

(3)兼容性的問題,ie8以前的瀏覽器不支持。

一般一些網站的小圖標可以使用base64圖片來引入。

詳細資料可以參考: 《玩轉圖片 base64 編碼》 《前端開發中,使用 base64 圖片的弊端是什麼?》 《小 tip:base64:URL 背景圖片與 web 頁面性能優化》

25.‘display’、'position’和’float’的相互關係?

(1)首先我們判斷display屬性是否爲none,如果爲none,則position和float屬性的值不影響元素最後的表現。

(2)然後判斷position的值是否爲absolute或者fixed,如果是,則float屬性失效,並且display的值應該被
設置爲table或者block,具體轉換需要看初始轉換值。

(3)如果position的值不爲absolute或者fixed,則判斷float屬性的值是否爲none,如果不是,則display
的值則按上面的規則轉換。注意,如果position的值爲relative並且float屬性的值存在,則relative相對
於浮動後的最終位置定位。

(4)如果float的值爲none,則判斷元素是否爲根元素,如果是根元素則display屬性按照上面的規則轉換,如果不是,
則保持指定的display屬性值不變。

總的來說,可以把它看作是一個類似優先級的機制,"position:absolute"和"position:fixed"優先級最高,有它存在
的時候,浮動不起作用,'display'的值也需要調整;其次,元素的'float'特性的值不是"none"的時候或者它是根元素
的時候,調整'display'的值;最後,非根元素,並且非浮動元素,並且非絕對定位的元素,'display'特性值同設置值。

詳細資料可以參考: 《position 跟 display、margincollapse、overflow、float 這些特性相互疊加後會怎麼樣?》

26.margin 重疊問題的理解。

相關知識點:

塊級元素的上外邊距(margin-top)與下外邊距(margin-bottom)有時會合併爲單個外邊距,這樣的現象稱爲“margin合
並”。

產生摺疊的必備條件:margin必須是鄰接的!

而根據w3c規範,兩個margin是鄰接的必須滿足以下條件:

•必須是處於常規文檔流(非float和絕對定位)的塊級盒子,並且處於同一個BFC當中。
•沒有線盒,沒有空隙,沒有padding和border將他們分隔開
•都屬於垂直方向上相鄰的外邊距,可以是下面任意一種情況
•元素的margin-top與其第一個常規文檔流的子元素的margin-top
•元素的margin-bottom與其下一個常規文檔流的兄弟元素的margin-top
•height爲auto的元素的margin-bottom與其最後一個常規文檔流的子元素的margin-bottom
•高度爲0並且最小高度也爲0,不包含常規文檔流的子元素,並且自身沒有建立新的BFC的元素的margin-top
和margin-bottom


margin合併的3種場景:

(1)相鄰兄弟元素margin合併。

解決辦法:
•設置塊狀格式化上下文元素(BFC)

(2)父級和第一個/最後一個子元素的margin合併。

解決辦法:

對於margin-top合併,可以進行如下操作(滿足一個條件即可):
•父元素設置爲塊狀格式化上下文元素;
•父元素設置border-top值;
•父元素設置padding-top值;
•父元素和第一個子元素之間添加內聯元素進行分隔。

對於margin-bottom合併,可以進行如下操作(滿足一個條件即可):
•父元素設置爲塊狀格式化上下文元素;
•父元素設置border-bottom值;
•父元素設置padding-bottom值;
•父元素和最後一個子元素之間添加內聯元素進行分隔;
•父元素設置height、min-height或max-height。

(3)空塊級元素的margin合併。

解決辦法:
•設置垂直方向的border;
•設置垂直方向的padding;
•裏面添加內聯元素(直接Space鍵空格是沒用的);
•設置height或者min-height。

回答:

margin重疊指的是在垂直方向上,兩個相鄰元素的margin發生重疊的情況。

一般來說可以分爲四種情形:

第一種是相鄰兄弟元素的marin-bottom和margin-top的值發生重疊。這種情況下我們可以通過設置其中一個元素爲BFC
來解決。

第二種是父元素的margin-top和子元素的margin-top發生重疊。它們發生重疊是因爲它們是相鄰的,所以我們可以通過這
一點來解決這個問題。我們可以爲父元素設置border-top、padding-top值來分隔它們,當然我們也可以將父元素設置爲BFC
來解決。

第三種是高度爲auto的父元素的margin-bottom和子元素的margin-bottom發生重疊。它們發生重疊一個是因爲它們相
鄰,一個是因爲父元素的高度不固定。因此我們可以爲父元素設置border-bottom、padding-bottom來分隔它們,也可以爲
父元素設置一個高度,max-height和min-height也能解決這個問題。當然將父元素設置爲BFC是最簡單的方法。

第四種情況,是沒有內容的元素,自身的margin-top和margin-bottom發生的重疊。我們可以通過爲其設置border、pa
dding或者高度來解決這個問題。

27.對 BFC 規範(塊級格式化上下文:blockformattingcontext)的理解?

相關知識點:

塊格式化上下文(BlockFormattingContext,BFC)是Web頁面的可視化CSS渲染的一部分,是佈局過程中生成塊級盒
子的區域,也是浮動元素與其他元素的交互限定區域。

通俗來講

•BFC是一個獨立的佈局環境,可以理解爲一個容器,在這個容器中按照一定規則進行物品擺放,並且不會影響其它環境中的物品。
•如果一個元素符合觸發BFC的條件,則BFC中的元素佈局不受外部影響。

創建BFC

(1)根元素或包含根元素的元素
(2)浮動元素float=left|right或inherit(≠none)
(3)絕對定位元素position=absolute或fixed
(4)display=inline-block|flex|inline-flex|table-cell或table-caption
(5)overflow=hidden|auto或scroll(≠visible)

回答:

BFC指的是塊級格式化上下文,一個元素形成了BFC之後,那麼它內部元素產生的佈局不會影響到外部元素,外部元素的佈局也
不會影響到BFC中的內部元素。一個BFC就像是一個隔離區域,和其他區域互不影響。

一般來說根元素是一個BFC區域,浮動和絕對定位的元素也會形成BFC,display屬性的值爲inline-block、flex這些
屬性時也會創建BFC。還有就是元素的overflow的值不爲visible時都會創建BFC。

詳細資料可以參考: 《深入理解 BFC 和 MarginCollapse》 《前端面試題-BFC(塊格式化上下文)》

28.IFC 是什麼?

IFC指的是行級格式化上下文,它有這樣的一些佈局規則:

(1)行級上下文內部的盒子會在水平方向,一個接一個地放置。
(2)當一行不夠的時候會自動切換到下一行。
(3)行級上下文的高度由內部最高的內聯盒子的高度決定。

詳細資料可以參考: [《譯]:BFC 與 IFC》 《BFC 和 IFC 的理解(佈局)》

29.請解釋一下爲什麼需要清除浮動?清除浮動的方式

浮動元素可以左右移動,直到遇到另一個浮動元素或者遇到它外邊緣的包含框。浮動框不屬於文檔流中的普通流,當元素浮動之後,
不會影響塊級元素的佈局,只會影響內聯元素佈局。此時文檔流中的普通流就會表現得該浮動框不存在一樣的佈局模式。當包含框
的高度小於浮動框的時候,此時就會出現“高度塌陷”。

清除浮動是爲了清除使用浮動元素產生的影響。浮動的元素,高度會塌陷,而高度的塌陷使我們頁面後面的佈局不能正常顯示。

清除浮動的方式

(1)使用clear屬性清除浮動。參考28。

(2)使用BFC塊級格式化上下文來清除浮動。參考26。

因爲BFC元素不會影響外部元素的特點,所以BFC元素也可以用來清除浮動的影響,因爲如果不清除,子元素浮動則父元
素高度塌陷,必然會影響後面元素佈局和定位,這顯然有違BFC元素的子元素不會影響外部元素的設定。

30.使用 clear 屬性清除浮動的原理?

使用clear屬性清除浮動,其語法如下:

clear:none|left|right|both

如果單看字面意思,clear:left應該是“清除左浮動”,clear:right應該是“清除右浮動”的意思,實際上,這種解釋是有問
題的,因爲浮動一直還在,並沒有清除。

官方對clear屬性的解釋是:“元素盒子的邊不能和前面的浮動元素相鄰。”,我們對元素設置clear屬性是爲了避免浮動元素
對該元素的影響,而不是清除掉浮動。

還需要注意的一點是clear屬性指的是元素盒子的邊不能和前面的浮動元素相鄰,注意這裏“前面的”3個字,也就是clear屬
性對“後面的”浮動元素是不聞不問的。考慮到float屬性要麼是left,要麼是right,不可能同時存在,同時由於clear
屬性對“後面的”浮動元素不聞不問,因此,當clear:left有效的時候,clear:right必定無效,也就是此時clear:left
等同於設置clear:both;同樣地,clear:right如果有效也是等同於設置clear:both。由此可見,clear:left和cle
ar:right這兩個聲明就沒有任何使用的價值,至少在CSS世界中是如此,直接使用clear:both吧。

一般使用僞元素的方式清除浮動

.clear::after{
content:'';
display:table;//也可以是'block',或者是'list-item'
clear:both;
}

clear屬性只有塊級元素纔有效的,而::after等僞元素默認都是內聯水平,這就是藉助僞元素清除浮動影響時需要設置disp
lay屬性值的原因。

31.zoom:1 的清除浮動原理?

清除浮動,觸發hasLayout;
zoom屬性是IE瀏覽器的專有屬性,它可以設置或檢索對象的縮放比例。解決ie下比較奇葩的bug。譬如外邊距(margin)
的重疊,浮動清除,觸發ie的haslayout屬性等。

來龍去脈大概如下:
當設置了zoom的值之後,所設置的元素就會就會擴大或者縮小,高度寬度就會重新計算了,這裏一旦改變zoom值時其實也會發
生重新渲染,運用這個原理,也就解決了ie下子元素浮動時候父元素不隨着自動擴大的問題。

zoom屬性是IE瀏覽器的專有屬性,火狐和老版本的webkit核心的瀏覽器都不支持這個屬性。然而,zoom現在已經被逐步標
準化,出現在CSS3.0規範草案中。

目前非ie由於不支持這個屬性,它們又是通過什麼屬性來實現元素的縮放呢?可以通過css3裏面的動畫屬性scale進行縮放。

32.移動端的佈局用過媒體查詢嗎?

假設你現在正用一臺顯示設備來閱讀這篇文章,同時你也想把它投影到屏幕上,或者打印出來,而顯示設備、屏幕投影和打印等這些
媒介都有自己的特點,CSS就是爲文檔提供在不同媒介上展示的適配方法

當媒體查詢爲真時,相關的樣式表或樣式規則會按照正常的級聯規被應用。當媒體查詢返回假,標籤上帶有媒體查詢的樣式表仍將被
下載(只不過不會被應用)。

包含了一個媒體類型和至少一個使用寬度、高度和顏色等媒體屬性來限制樣式表範圍的表達式。CSS3加入的媒體查詢使得無需修改
內容便可以使樣式應用於某些特定的設備範圍。

詳細資料可以參考: 《CSS3@media 查詢》 《響應式佈局和自適應佈局詳解》

33.使用 CSS 預處理器嗎?喜歡哪個?

SASS(SASS、LESS沒有本質區別,只因爲團隊前端都是用的SASS)

34.CSS 優化、提高性能的方法有哪些?

加載性能:

(1)css壓縮:將寫好的css進行打包壓縮,可以減少很多的體積。
(2)css單一樣式:當需要下邊距和左邊距的時候,很多時候選擇:margin:top0bottom0;但margin-bottom:bot
tom;margin-left:left;執行的效率更高。
(3)減少使用@import,而建議使用link,因爲後者在頁面加載時一起加載,前者是等待頁面加載完成之後再進行加載。

選擇器性能:

(1)關鍵選擇器(keyselector)。選擇器的最後面的部分爲關鍵選擇器(即用來匹配目標元素的部分)。CSS選擇符是從右到
左進行匹配的。當使用後代選擇器的時候,瀏覽器會遍歷所有子元素來確定是否是指定的元素等等;

(2)如果規則擁有ID選擇器作爲其關鍵選擇器,則不要爲規則增加標籤。過濾掉無關的規則(這樣樣式系統就不會浪費時間去匹
配它們了)。

(3)避免使用通配規則,如*{}計算次數驚人!只對需要用到的元素進行選擇。

(4)儘量少的去對標籤進行選擇,而是用class。

(5)儘量少的去使用後代選擇器,降低選擇器的權重值。後代選擇器的開銷是最高的,儘量將選擇器的深度降到最低,最高不要超過
三層,更多的使用類來關聯每一個標籤元素。

(6)瞭解哪些屬性是可以通過繼承而來的,然後避免對這些屬性重複指定規則。

渲染性能:

(1)慎重使用高性能屬性:浮動、定位。

(2)儘量減少頁面重排、重繪。

(3)去除空規則:{}。空規則的產生原因一般來說是爲了預留樣式。去除這些空規則無疑能減少css文檔體積。

(4)屬性值爲0時,不加單位。

(5)屬性值爲浮動小數0.**,可以省略小數點之前的0。

(6)標準化各種瀏覽器前綴:帶瀏覽器前綴的在前。標準屬性在後。

(7)不使用@import前綴,它會影響css的加載速度。

(8)選擇器優化嵌套,儘量避免層級過深。

(9)css雪碧圖,同一頁面相近部分的小圖標,方便使用,減少頁面的請求次數,但是同時圖片本身會變大,使用時,優劣考慮清
楚,再使用。

(10)正確使用display的屬性,由於display的作用,某些樣式組合會無效,徒增樣式體積的同時也影響解析性能。

(11)不濫用web字體。對於中文網站來說WebFonts可能很陌生,國外卻很流行。webfonts通常體積龐大,而且一些瀏
覽器在下載webfonts時會阻塞頁面渲染損傷性能。

可維護性、健壯性:

(1)將具有相同屬性的樣式抽離出來,整合並通過class在頁面中進行使用,提高css的可維護性。
(2)樣式與內容分離:將css代碼定義到外部css中。

詳細資料可以參考: 《CSS 優化、提高性能的方法有哪些?》 《CSS 優化,提高性能的方法》

35.瀏覽器是怎樣解析 CSS 選擇器的?

樣式系統從關鍵選擇器開始匹配,然後左移查找規則選擇器的祖先元素。只要選擇器的子樹一直在工作,樣式系統就會持續左移,直
到和規則匹配,或者是因爲不匹配而放棄該規則。

試想一下,如果採用從左至右的方式讀取CSS規則,那麼大多數規則讀到最後(最右)纔會發現是不匹配的,這樣做會費時耗能,
最後有很多都是無用的;而如果採取從右向左的方式,那麼只要發現最右邊選擇器不匹配,就可以直接捨棄了,避免了許多無效匹配。

詳細資料可以參考: 《探究 CSS 解析原理》

36.在網頁中應該使用奇數還是偶數的字體?爲什麼呢?

(1)偶數字號相對更容易和web設計的其他部分構成比例關係。比如:當我用了14px的正文字號,我可能會在一些地方用14
×0.5=7px的margin,在另一些地方用14×1.5=21px的標題字號。
(2)瀏覽器緣故,低版本的瀏覽器ie6會把奇數字體強制轉化爲偶數,即13px渲染爲14px。
(3)系統差別,早期的Windows裏,中易宋體點陣只有12和14、15、16px,唯獨缺少13px。

詳細資料可以參考: 《談談網頁中使用奇數字體和偶數字體》 《現在網頁設計中的爲什麼少有人用 11px、13px、15px 等奇數的字體?》

37.margin 和 padding 分別適合什麼場景使用?

margin是用來隔開元素與元素的間距;padding是用來隔開元素與內容的間隔。
margin用於佈局分開元素使元素與元素互不相干。
padding用於元素與內容之間的間隔,讓內容(文字)與(包裹)元素之間有一段距離。

何時應當使用margin:
•需要在border外側添加空白時。
•空白處不需要背景(色)時。
•上下相連的兩個盒子之間的空白,需要相互抵消時。如15px+20px的margin,將得到20px的空白。

何時應當時用padding:
•需要在border內測添加空白時。
•空白處需要背景(色)時。
•上下相連的兩個盒子之間的空白,希望等於兩者之和時。如15px+20px的padding,將得到35px的空白。

38.抽離樣式模塊怎麼寫,說出思路,有無實踐經驗?[阿里航旅的面試題]

我的理解是把常用的css樣式單獨做成css文件……通用的和業務相關的分離出來,通用的做成樣式模塊兒共享,業務相關的,放
進業務相關的庫裏面做成對應功能的模塊兒。

詳細資料可以參考: 《CSS 規範-分類方法》

39.簡單說一下 css3 的 all 屬性。

all屬性實際上是所有CSS屬性的縮寫,表示,所有的CSS屬性都怎樣怎樣,但是,不包括unicode-bidi和direction
這兩個CSS屬性。支持三個CSS通用屬性值,initial,inherit,unset。

initial是初始值的意思,也就是該元素元素都除了unicode-bidi和direction以外的CSS屬性都使用屬性的默認初始
值。

inherit是繼承的意思,也就是該元素除了unicode-bidi和direction以外的CSS屬性都繼承父元素的屬性值。

unset是取消設置的意思,也就是當前元素瀏覽器或用戶設置的CSS忽略,然後如果是具有繼承特性的CSS,如color,則
使用繼承值;如果是沒有繼承特性的CSS屬性,如background-color,則使用初始值。

詳細資料可以參考: 《簡單瞭解 CSS3 的 all 屬性》

40.爲什麼不建議使用統配符初始化 css 樣式。

採用*{pading:0;margin:0;}這樣的寫法好處是寫起來很簡單,但是是通配符,需要把所有的標籤都遍歷一遍,當網站較大時,
樣式比較多,這樣寫就大大的加強了網站運行的負載,會使網站加載的時候需要很長一段時間,因此一般大型的網站都有分層次的一
套初始化樣式。

出於性能的考慮,並不是所有標籤都會有padding和margin,因此對常見的具有默認padding和margin的元素初始化即
可,並不需使用通配符*來初始化。

41.absolute 的 containingblock(包含塊)計算方式跟正常流有什麼不同?

(1)內聯元素也可以作爲“包含塊”所在的元素;

(2)“包含塊”所在的元素不是父塊級元素,而是最近的position不爲static的祖先元素或根元素;

(3)邊界是paddingbox而不是contentbox。

42.對於 hasLayout 的理解?

hasLayout是IE特有的一個屬性。很多的IE下的cssbug都與其息息相關。在IE中,一個元素要麼自己對自身的內容進
行計算大小和組織,要麼依賴於父元素來計算尺寸和組織內容。當一個元素的hasLayout屬性值爲true時,它負責對自己和可
能的子孫元素進行尺寸計算和定位。雖然這意味着這個元素需要花更多的代價來維護自身和裏面的內容,而不是依賴於祖先元素來完
成這些工作。

詳細資料可以參考: 《CSS 基礎篇–CSS 中 IE 瀏覽器的 hasLayout,IE 低版本的 bug 根源》 《CSS 魔法堂:hasLayout 原來是這樣的!》

43.元素豎向的百分比設定是相對於容器的高度嗎?

如果是height的話,是相對於包含塊的高度。

如果是padding或者margin豎直方向的屬性則是相對於包含塊的寬度。

44.全屏滾動的原理是什麼?用到了 CSS 的哪些屬性?(待深入實踐)

原理:有點類似於輪播,整體的元素一直排列下去,假設有5個需要展示的全屏頁面,那麼高度是500%,只是展示100%,容器及容
器內的頁面取當前可視區高度,同時容器的父級元素overflow屬性值設爲hidden,通過更改容器可視區的位置來實現全
屏滾動效果。主要是響應鼠標事件,頁面通過CSS的動畫效果,進行移動。

overflow:hidden;transition:all1000msease;

詳細資料可以參考: 《js 實現網頁全屏切換(平滑過渡),鼠標滾動切換》 《用 ES6 寫全屏滾動插件》

45.什麼是響應式設計?響應式設計的基本原理是什麼?如何兼容低版本的 IE?(待深入瞭解)

響應式網站設計是一個網站能夠兼容多個終端,而不是爲每一個終端做一個特定的版本。基本原理是通過媒體查詢檢測不同的設備屏
幕尺寸做處理。頁面頭部必須有meta聲明的viewport。

詳細資料可以參考: 《響應式佈局原理》 《響應式佈局的實現方法和原理》

46.視差滾動效果,如何給每頁做不同的動畫?(回到頂部,向下滑動要再次出現,和只出現一次分別怎麼做?)

視差滾動是指多層背景以不同的速度移動,形成立體的運動效果,帶來非常出色的視覺體驗。

詳細資料可以參考: 《如何實現視差滾動效果的網頁?》

47.如何修改 chrome 記住密碼後自動填充表單的黃色背景?

chrome表單自動填充後,input文本框的背景會變成黃色的,通過審查元素可以看到這是由於chrome會默認給自動填充的in
put表單加上input:-webkit-autofill私有屬性,然後對其賦予以下樣式:

{
background-color:rgb(250,255,189)!important;
background-image:none!important;
color:rgb(0,0,0)!important;
}

對chrome默認定義的background-color,background-image,color使用important是不能提高其優先級的,但是
其他屬性可使用。

使用足夠大的純色內陰影來覆蓋input輸入框的黃色背景,處理如下

input:-webkit-autofill,textarea:-webkit-autofill,select:-webkit-autofill{
-webkit-box-shadow:000px1000pxwhiteinset;
border:1pxsolid#CCC!important;
}

詳細資料可以參考: 《去掉 chrome 記住密碼後的默認填充樣式》 《修改谷歌瀏覽器 chrome 記住密碼後自動填充表單的黃色背景》

48.怎麼讓 Chrome 支持小於 12px 的文字?

在谷歌下css設置字體大小爲12px及以下時,顯示都是一樣大小,都是默認12px。

解決辦法:

(1)可以使用Webkit的內核的-webkit-text-size-adjust的私有CSS屬性來解決,只要加了-webkit-text-size
-adjust:none;字體大小就不受限制了。但是chrome更新到27版本之後就不可以用了。所以高版本chrome谷歌瀏覽器
已經不再支持-webkit-text-size-adjust樣式,所以要使用時候慎用。

(2)還可以使用css3的transform縮放屬性-webkit-transform:scale(0.5);注意-webkit-transform:scale(0.
75);收縮的是整個元素的大小,這時候,如果是內聯元素,必須要將內聯元素轉換成塊元素,可以使用display:block/
inline-block/...;

(3)使用圖片:如果是內容固定不變情況下,使用將小於12px文字內容切出做圖片,這樣不影響兼容也不影響美觀。

詳細資料可以參考: 《谷歌瀏覽器不支持 CSS 設置小於 12px 的文字怎麼辦?》

49.讓頁面裏的字體變清晰,變細用 CSS 怎麼做?

webkit內核的私有屬性:-webkit-font-smoothing,用於字體抗鋸齒,使用後字體看起來會更清晰舒服。

在MacOS測試環境下面設置-webkit-font-smoothing:antialiased;但是這個屬性僅僅是面向MacOS,其他操作系統設
置後無效。

詳細資料可以參考: 《讓字體變的更清晰 CSS 中-webkit-font-smoothing》

50.font-style 屬性中 italic 和 oblique 的區別?

italic和oblique這兩個關鍵字都表示“斜體”的意思。

它們的區別在於,italic是使用當前字體的斜體字體,而oblique只是單純地讓文字傾斜。如果當前字體沒有對應的斜體字體,
則退而求其次,解析爲oblique,也就是單純形狀傾斜。

51.設備像素、css 像素、設備獨立像素、dpr、ppi 之間的區別?

設備像素指的是物理像素,一般手機的分辨率指的就是設備像素,一個設備的設備像素是不可變的。

css像素和設備獨立像素是等價的,不管在何種分辨率的設備上,css像素的大小應該是一致的,css像素是一個相對單位,它是相
對於設備像素的,一個css像素的大小取決於頁面縮放程度和dpr的大小。

dpr指的是設備像素和設備獨立像素的比值,一般的pc屏幕,dpr=1。在iphone4時,蘋果推出了retina屏幕,它的dpr
爲2。屏幕的縮放會改變dpr的值。

ppi指的是每英寸的物理像素的密度,ppi越大,屏幕的分辨率越大。

詳細資料可以參考: 《什麼是物理像素、虛擬像素、邏輯像素、設備像素,什麼又是 PPI,DPI,DPR 和 DIP》 《前端工程師需要明白的「像素」》 《CSS 像素、物理像素、邏輯像素、設備像素比、PPI、Viewport》 《前端開發中像素的概念》

52.layoutviewport、visualviewport 和 idealviewport 的區別?

相關知識點:

如果把移動設備上瀏覽器的可視區域設爲viewport的話,某些網站就會因爲viewport太窄而顯示錯亂,所以這些瀏覽器就決定
默認情況下把viewport設爲一個較寬的值,比如980px,這樣的話即使是那些爲桌面設計的網站也能在移動瀏覽器上正常顯示了。
ppk把這個瀏覽器默認的viewport叫做layoutviewport。

layoutviewport的寬度是大於瀏覽器可視區域的寬度的,所以我們還需要一個viewport來代表瀏覽器可視區域的大小,ppk把
這個viewport叫做visualviewport。

idealviewport是最適合移動設備的viewport,idealviewport的寬度等於移動設備的屏幕寬度,只要在css中把某一元
素的寬度設爲idealviewport的寬度(單位用px),那麼這個元素的寬度就是設備屏幕的寬度了,也就是寬度爲100%的效果。i
dealviewport的意義在於,無論在何種分辨率的屏幕下,那些針對idealviewport而設計的網站,不需要用戶手動縮放,也
不需要出現橫向滾動條,都可以完美的呈現給用戶。

回答:

移動端一共需要理解三個viewport的概念的理解。

第一個視口是佈局視口,在移動端顯示網頁時,由於移動端的屏幕尺寸比較小,如果網頁使用移動端的屏幕尺寸進行佈局的話,那麼整
個頁面的佈局都會顯示錯亂。所以移動端瀏覽器提供了一個layoutviewport佈局視口的概念,使用這個視口來對頁面進行佈局展
示,一般layoutviewport的大小爲980px,因此頁面佈局不會有太大的變化,我們可以通過拖動和縮放來查看到這個頁面。

第二個視口指的是視覺視口,visualviewport指的是移動設備上我們可見的區域的視口大小,一般爲屏幕的分辨率的大小。visu
alviewport和layoutviewport的關係,就像是我們通過窗戶看外面的風景,視覺視口就是窗戶,而外面的風景就是佈局視口
中的網頁內容。

第三個視口是理想視口,由於layoutviewport一般比visualviewport要大,所以想要看到整個頁面必須通過拖動和縮放才
能實現。所以又提出了idealviewport的概念,idealviewport下用戶不用縮放和滾動條就能夠查看到整個頁面,並且頁面在
不同分辨率下顯示的內容大小相同。idealviewport其實就是通過修改layoutviewport的大小,讓它等於設備的寬度,這個
寬度可以理解爲是設備獨立像素,因此根據idealviewport設計的頁面,在不同分辨率的屏幕下,顯示應該相同。

詳細資料可以參考: 《移動前端開發之 viewport 的深入理解》 《說說移動前端中 viewport(視口)》 《移動端適配知識你到底知多少》

53.position:fixed;在 android 下無效怎麼處理?

因爲移動端瀏覽器默認的viewport叫做layoutviewport。在移動端顯示時,因爲layoutviewport的寬度大於移動端屏幕
的寬度,所以頁面會出現滾動條左右移動,fixed的元素是相對layoutviewport來固定位置的,而不是移動端屏幕來固定位置的
,所以會出現感覺fixed無效的情況。

如果想實現fixed相對於屏幕的固定效果,我們需要改變的是viewport的大小爲idealviewport,可以如下設置:

<metaname="viewport"content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-sca
le=1.0,user-scalable=no"/>

54.如果需要手動寫動畫,你認爲最小時間間隔是多久,爲什麼?(阿里)

多數顯示器默認頻率是60Hz,即1秒刷新60次,所以理論上最小間隔爲1/60*1000ms=16.7ms

55.如何讓去除 inline-block 元素間間距?

移除空格、使用margin負值、使用font-size:0、letter-spacing、word-spacing

詳細資料可以參考: 《去除 inline-block 元素間間距的 N 種方法》

56.overflow:scroll 時不能平滑滾動的問題怎麼處理?

以下代碼可解決這種卡頓的問題:-webkit-overflow-scrolling:touch;是因爲這行代碼啓用了硬件加速特性,所以滑動很流
暢。

詳細資料可以參考: 《解決頁面使用 overflow:scroll 在 iOS 上滑動卡頓的問題》

57.有一個高度自適應的 div,裏面有兩個 div,一個高度 100px,希望另一個填滿剩下的高度。

(1)外層div使用position:relative;高度要求自適應的div使用position:absolute;top:100px;bottom:0;
left:0;right:0;

(2)使用flex佈局,設置主軸爲豎軸,第二個div的flex-grow爲1。

詳細資料可以參考: 《有一個高度自適應的 div,裏面有兩個 div,一個高度 100px,希望另一個填滿剩下的高度(三種方案)》

58.png、jpg、gif 這些圖片格式解釋一下,分別什麼時候用。有沒有了解過 webp?

相關知識點:

(1)BMP,是無損的、既支持索引色也支持直接色的、點陣圖。這種圖片格式幾乎沒有對數據進行壓縮,所以BMP格式的圖片通常
具有較大的文件大小。

(2)GIF是無損的、採用索引色的、點陣圖。採用LZW壓縮算法進行編碼。文件小,是GIF格式的優點,同時,GIF格式還具
有支持動畫以及透明的優點。但,GIF格式僅支持8bit的索引色,所以GIF格式適用於對色彩要求不高同時需要文件體積
較小的場景。

(3)JPEG是有損的、採用直接色的、點陣圖。JPEG的圖片的優點,是採用了直接色,得益於更豐富的色彩,JPEG非常適合用來
存儲照片,與GIF相比,JPEG不適合用來存儲企業Logo、線框類的圖。因爲有損壓縮會導致圖片模糊,而直接色的選用,
又會導致圖片文件較GIF更大。

(4)PNG-8是無損的、使用索引色的、點陣圖。PNG是一種比較新的圖片格式,PNG-8是非常好的GIF格式替代者,在可能的
情況下,應該儘可能的使用PNG-8而不是GIF,因爲在相同的圖片效果下,PNG-8具有更小的文件體積。除此之外,PNG-8
還支持透明度的調節,而GIF並不支持。現在,除非需要動畫的支持,否則我們沒有理由使用GIF而不是PNG-8。

(5)PNG-24是無損的、使用直接色的、點陣圖。PNG-24的優點在於,它壓縮了圖片的數據,使得同樣效果的圖片,PNG-24格
式的文件大小要比BMP小得多。當然,PNG24的圖片還是要比JPEG、GIF、PNG-8大得多。

(6)SVG是無損的、矢量圖。SVG是矢量圖。這意味着SVG圖片由直線和曲線以及繪製它們的方法組成。當你放大一個SVG圖
片的時候,你看到的還是線和曲線,而不會出現像素點。這意味着SVG圖片在放大時,不會失真,所以它非常適合用來繪製企
業Logo、Icon等。

(7)WebP是谷歌開發的一種新圖片格式,WebP是同時支持有損和無損壓縮的、使用直接色的、點陣圖。從名字就可以看出來它是
爲Web而生的,什麼叫爲Web而生呢?就是說相同質量的圖片,WebP具有更小的文件體積。現在網站上充滿了大量的圖片,
如果能夠降低每一個圖片的文件大小,那麼將大大減少瀏覽器和服務器之間的數據傳輸量,進而降低訪問延遲,提升訪問體驗。

•在無損壓縮的情況下,相同質量的WebP圖片,文件大小要比PNG小26%;
•在有損壓縮的情況下,具有相同圖片精度的WebP圖片,文件大小要比JPEG小25%~34%;
•WebP圖片格式支持圖片透明度,一個無損壓縮的WebP圖片,如果要支持透明度只需要22%的格外文件大小。

但是目前只有Chrome瀏覽器和Opera瀏覽器支持WebP格式,兼容性不太好。

回答:

我瞭解到的一共有七種常見的圖片的格式。

(1)第一種是BMP格式,它是無損壓縮的,支持索引色和直接色的點陣圖。由於它基本上沒有進行壓縮,因此它的文件體積一般比
較大。

(2)第二種是GIF格式,它是無損壓縮的使用索引色的點陣圖。由於使用了LZW壓縮方法,因此文件的體積很小。並且GIF還
支持動畫和透明度。但因爲它使用的是索引色,所以它適用於一些對顏色要求不高且需要文件體積小的場景。

(3)第三種是JPEG格式,它是有損壓縮的使用直接色的點陣圖。由於使用了直接色,色彩較爲豐富,一般適用於來存儲照片。但
由於使用的是直接色,可能文件的體積相對於GIF格式來說更大。

(4)第四種是PNG-8格式,它是無損壓縮的使用索引色的點陣圖。它是GIF的一種很好的替代格式,它也支持透明度的調整,並
且文件的體積相對於GIF格式更小。一般來說如果不是需要動畫的情況,我們都可以使用PNG-8格式代替GIF格式。

(5)第五種是PNG-24格式,它是無損壓縮的使用直接色的點陣圖。PNG-24的優點是它使用了壓縮算法,所以它的體積比BMP
格式的文件要小得多,但是相對於其他的幾種格式,還是要大一些。

(6)第六種格式是svg格式,它是矢量圖,它記錄的圖片的繪製方式,因此對矢量圖進行放大和縮小不會產生鋸齒和失真。它一般
適合於用來製作一些網站logo或者圖標之類的圖片。

(7)第七種格式是webp格式,它是支持有損和無損兩種壓縮方式的使用直接色的點陣圖。使用webp格式的最大的優點是,在相
同質量的文件下,它擁有更小的文件體積。因此它非常適合於網絡圖片的傳輸,因爲圖片體積的減少,意味着請求時間的減小,
這樣會提高用戶的體驗。這是谷歌開發的一種新的圖片格式,目前在兼容性上還不是太好。

詳細資料可以參考: 《圖片格式那麼多,哪種更適合你?》

59.瀏覽器如何判斷是否支持 webp 格式圖片

(1)寬高判斷法。通過創建image對象,將其src屬性設置爲webp格式的圖片,然後在onload事件中獲取圖片的寬高,如
果能夠獲取,則說明瀏覽器支持webp格式圖片。如果不能獲取或者觸發了onerror函數,那麼就說明瀏覽器不支持webp格
式的圖片。

(2)canvas判斷方法。我們可以動態的創建一個canvas對象,通過canvas的toDataURL將設置爲webp格式,然後判斷
返回值中是否含有image/webp字段,如果包含則說明支持WebP,反之則不支持。

詳細資料可以參考: 《判斷瀏覽器是否支持 WebP 圖片》 《toDataURL()》

60.什麼是 Cookie 隔離?(或者說:請求資源的時候不要讓它帶 cookie 怎麼做)

網站向服務器請求的時候,會自動帶上cookie這樣增加表頭信息量,使請求變慢。

如果靜態文件都放在主域名下,那靜態文件請求的時候都帶有的cookie的數據提交給server的,非常浪費流量,所以不如隔離開
,靜態資源放CDN。

因爲cookie有域的限制,因此不能跨域提交請求,故使用非主要域名的時候,請求頭中就不會帶有cookie數據,這樣可以降低請
求頭的大小,降低請求時間,從而達到降低整體請求延時的目的。

同時這種方式不會將cookie傳入WebServer,也減少了WebServer對cookie的處理分析環節,提高了webserver的
http請求的解析速度。

詳細資料可以參考: 《CDN 是什麼?使用 CDN 有什麼優勢?》

61.style 標籤寫在 body 後與 body 前有什麼區別?

頁面加載自上而下當然是先加載樣式。寫在body標籤後由於瀏覽器以逐行方式對HTML文檔進行解析,當解析到寫在尾部的樣式
表(外聯或寫在style標籤)會導致瀏覽器停止之前的渲染,等待加載且解析樣式表完成之後重新渲染,在windows的IE下可
能會出現FOUC現象(即樣式失效導致的頁面閃爍問題)

62.什麼是 CSS 預處理器/後處理器?

CSS預處理器定義了一種新的語言,其基本思想是,用一種專門的編程語言,爲CSS增加了一些編程的特性,將CSS作爲目標生成
文件,然後開發者就只要使用這種語言進行編碼工作。通俗的說,CSS預處理器用一種專門的編程語言,進行Web頁面樣式設計,然
後再編譯成正常的CSS文件。

預處理器例如:LESS、Sass、Stylus,用來預編譯Sass或lesscsssprite,增強了css代碼的複用性,還有層級、mixin、
變量、循環、函數等,具有很方便的UI組件模塊化開發能力,極大的提高工作效率。

CSS後處理器是對CSS進行處理,並最終生成CSS的預處理器,它屬於廣義上的CSS預處理器。我們很久以前就在用CSS後
處理器了,最典型的例子是CSS壓縮工具(如clean-css),只不過以前沒單獨拿出來說過。還有最近比較火的Autoprefixer,
以CanIUse上的瀏覽器支持數據爲基礎,自動處理兼容性問題。

後處理器例如:PostCSS,通常被視爲在完成的樣式表中根據CSS規範處理CSS,讓其更有效;目前最常做的是給CSS屬性添加瀏
覽器私有前綴,實現跨瀏覽器兼容性的問題。

詳細資料可以參考: 《CSS 預處理器和後處理器》

63.闡述一下 CSSSprites

將一個頁面涉及到的所有圖片都包含到一張大圖中去,然後利用CSS的background-image,background-repeat,background
-position的組合進行背景定位。利用CSSSprites能很好地減少網頁的http請求,從而很好的提高頁面的性能;CSSSprites
能減少圖片的字節。

優點:

減少HTTP請求數,極大地提高頁面加載速度
增加圖片信息重複度,提高壓縮比,減少圖片大小
更換風格方便,只需在一張或幾張圖片上修改顏色或樣式即可實現

缺點:

圖片合併麻煩
維護麻煩,修改一個圖片可能需要重新佈局整個圖片,樣式

64.使用 rem 佈局的優缺點?

優點:
在屏幕分辨率千差萬別的時代,只要將rem與屏幕分辨率關聯起來就可以實現頁面的整體縮放,使得在設備上的展現都統一起來了。
而且現在瀏覽器基本都已經支持rem了,兼容性也非常的好。

缺點:
(1)在奇葩的dpr設備上表現效果不太好,比如一些華爲的高端機型用rem佈局會出現錯亂。
(2)使用iframe引用也會出現問題。
(3)rem在多屏幕尺寸適配上與當前兩大平臺的設計哲學不一致。即大屏的出現到底是爲了看得又大又清楚,還是爲了看的更多的問
題。

詳細資料可以參考: 《css3 的字體大小單位 rem 到底好在哪?》 《VW:是時候放棄 REM 佈局了》 《爲什麼設計稿是 750px》 《使用 Flexible 實現手淘 H5 頁面的終端適配》

65.幾種常見的 CSS 佈局

詳細的資料可以參考: 《幾種常見的 CSS 佈局》

66.畫一條 0.5px 的線

採用metaviewport的方式

採用border-image的方式

採用transform:scale()的方式

詳細資料可以參考: 《怎麼畫一條 0.5px 的邊(更新)》

67.transition 和 animation 的區別

transition關注的是CSSproperty的變化,property值和時間的關係是一個三次貝塞爾曲線。

animation作用於元素本身而不是樣式屬性,可以使用關鍵幀的概念,應該說可以實現更自由的動畫效果。

詳細資料可以參考: 《CSSanimation 與 CSStransition 有何區別?》 《CSS3Transition 和 Animation 區別及比較》 《CSS 動畫簡介》 《CSS 動畫:animation、transition、transform、translate》

68.什麼是首選最小寬度?

“首選最小寬度”,指的是元素最適合的最小寬度。

東亞文字(如中文)最小寬度爲每個漢字的寬度。

西方文字最小寬度由特定的連續的英文字符單元決定。並不是所有的英文字符都會組成連續單元,一般會終止於空格(普通空格)、短
橫線、問號以及其他非英文字符等。

如果想讓英文字符和中文一樣,每一個字符都用最小寬度單元,可以試試使用CSS中的word-break:break-all。

69.爲什麼 height:100%會無效?

對於普通文檔流中的元素,百分比高度值要想起作用,其父級必須有一個可以生效的高度值。

原因是如果包含塊的高度沒有顯式指定(即高度由內容決定),並且該元素不是絕對定位,則計算值爲auto,因爲解釋成了auto,
所以無法參與計算。

使用絕對定位的元素會有計算值,即使祖先元素的height計算爲auto也是如此。

70.min-width/max-width 和 min-height/max-height 屬性間的覆蓋規則?

(1)max-width會覆蓋width,即使width是行類樣式或者設置了!important。

(2)min-width會覆蓋max-width,此規則發生在min-width和max-width衝突的時候。

71.內聯盒模型基本概念

(1)內容區域(contentarea)。內容區域指一種圍繞文字看不見的盒子,其大小僅受字符本身特性控制,本質上是一個字符盒子
(characterbox);但是有些元素,如圖片這樣的替換元素,其內容顯然不是文字,不存在字符盒子之類的,因此,對於這些
元素,內容區域可以看成元素自身。

(2)內聯盒子(inlinebox)。“內聯盒子”不會讓內容成塊顯示,而是排成一行,這裏的“內聯盒子”實際指的就是元素的“外在盒
子”,用來決定元素是內聯還是塊級。該盒子又可以細分爲“內聯盒子”和“匿名內聯盒子”兩類。

(3)行框盒子(linebox),每一行就是一個“行框盒子”(實線框標註),每個“行框盒子”又是由一個一個“內聯盒子”組成的。

(4)包含塊(containingbox),由一行一行的“行框盒子”組成。

72.什麼是幽靈空白節點?

“幽靈空白節點”是內聯盒模型中非常重要的一個概念,具體指的是:在HTML5文檔聲明中,內聯元素的所有解析和渲染表現就如同
每個行框盒子的前面有一個“空白節點”一樣。這個“空白節點”永遠透明,不佔據任何寬度,看不見也無法通過腳本獲取,就好像幽靈
一樣,但又確確實實地存在,表現如同文本節點一樣,因此,我稱之爲“幽靈空白節點”。

73.什麼是替換元素?

通過修改某個屬性值呈現的內容就可以被替換的元素就稱爲“替換元素”。因此,<img>、<object>、<video>、<iframe>或者表
單元素<textarea>和<input>和<select>都是典型的替換元素。

替換元素除了內容可替換這一特性以外,還有以下一些特性。

(1)內容的外觀不受頁面上的CSS的影響。用專業的話講就是在樣式表現在CSS作用域之外。如何更改替換元素本身的外觀需要
類似appearance屬性,或者瀏覽器自身暴露的一些樣式接口,

(2)有自己的尺寸。在Web中,很多替換元素在沒有明確尺寸設定的情況下,其默認的尺寸(不包括邊框)是300像素×150像
素,如<video>、<iframe>或者<canvas>等,也有少部分替換元素爲0像素,如<img>圖片,而表單元素的替換元素
的尺寸則和瀏覽器有關,沒有明顯的規律。

(3)在很多CSS屬性上有自己的一套表現規則。比較具有代表性的就是vertical-align屬性,對於替換元素和非替換元素,ve
rtical-align屬性值的解釋是不一樣的。比方說vertical-align的默認值的baseline,很簡單的屬性值,基線之意,
被定義爲字符x的下邊緣,而替換元素的基線卻被硬生生定義成了元素的下邊緣。

(4)所有的替換元素都是內聯水平元素,也就是替換元素和替換元素、替換元素和文字都是可以在一行顯示的。但是,替換元素默認
的display值卻是不一樣的,有的是inline,有的是inline-block。

74.替換元素的計算規則?

替換元素的尺寸從內而外分爲3類:固有尺寸、HTML尺寸和CSS尺寸。

(1)固有尺寸指的是替換內容原本的尺寸。例如,圖片、視頻作爲一個獨立文件存在的時候,都是有着自己的寬度和高度的。

(2)HTML尺寸只能通過HTML原生屬性改變,這些HTML原生屬性包括<img>的width和height屬性、<input>的s
ize屬性、<textarea>的cols和rows屬性等。

(3)CSS尺寸特指可以通過CSS的width和height或者max-width/min-width和max-height/min-height設置的
尺寸,對應盒尺寸中的contentbox。

這3層結構的計算規則具體如下

(1)如果沒有CSS尺寸和HTML尺寸,則使用固有尺寸作爲最終的寬高。

(2)如果沒有CSS尺寸,則使用HTML尺寸作爲最終的寬高。

(3)如果有CSS尺寸,則最終尺寸由CSS屬性決定。

(4)如果“固有尺寸”含有固有的寬高比例,同時僅設置了寬度或僅設置了高度,則元素依然按照固有的寬高比例顯示。

(5)如果上面的條件都不符合,則最終寬度表現爲300像素,高度爲150像素。

(6)內聯替換元素和塊級替換元素使用上面同一套尺寸計算規則。

75.content 與替換元素的關係?

content屬性生成的對象稱爲“匿名替換元素”。

(1)我們使用content生成的文本是無法選中、無法複製的,好像設置了userselect:none聲明一般,但是普通元素的文本
卻可以被輕鬆選中。同時,content生成的文本無法被屏幕閱讀設備讀取,也無法被搜索引擎抓取,因此,千萬不要自以爲是
地把重要的文本信息使用content屬性生成,因爲這對可訪問性和SEO都很不友好。

(2)content生成的內容不能左右:empty僞類。

(3)content動態生成值無法獲取。

76.margin:auto 的填充規則?

margin的'auto'可不是擺設,是具有強烈的計算意味的關鍵字,用來計算元素對應方向應該獲得的剩餘間距大小。但是觸發mar
gin:auto計算有一個前提條件,就是width或height爲auto時,元素是具有對應方向的自動填充特性的。

(1)如果一側定值,一側auto,則auto爲剩餘空間大小。
(2)如果兩側均是auto,則平分剩餘空間。

77.margin 無效的情形

(1)display計算值inline的非替換元素的垂直margin是無效的。對於內聯替換元素,垂直margin有效,並且沒有ma
rgin合併的問題。

(2)表格中的<tr>和<td>元素或者設置display計算值是table-cell或table-row的元素的margin都是無效的。

(3)絕對定位元素非定位方位的margin值“無效”。

(4)定高容器的子元素的margin-bottom或者寬度定死的子元素的margin-right的定位“失效”。

78.border 的特殊性?

(1)border-width卻不支持百分比。

(2)border-style的默認值是none,有一部分人可能會誤以爲是solid。這也是單純設置border-width或border-col
or沒有邊框顯示的原因。

(3)border-style:double的表現規則:雙線寬度永遠相等,中間間隔±1。

(4)border-color默認顏色就是color色值。

(5)默認background背景圖片是相對於paddingbox定位的。

79.什麼是基線和 x-height?

字母x的下邊緣(線)就是我們的基線。

x-height指的就是小寫字母x的高度,術語描述就是基線和等分線(meanline)(也稱作中線,midline)之間的距離。在C
SS世界中,middle指的是基線往上1/2x-height高度。我們可以近似理解爲字母x交叉點那個位置。

ex是CSS中的一個相對單位,指的是小寫字母x的高度,沒錯,就是指x-height。ex的價值就在其副業上不受字體和字號影
響的內聯元素的垂直居中對齊效果。內聯元素默認是基線對齊的,而基線就是x的底部,而1ex就是一個x的高度。

80.line-height 的特殊性?

(1)對於非替換元素的純內聯元素,其可視高度完全由line-height決定。對於文本這樣的純內聯元素,line-height就是高
度計算的基石,用專業說法就是指定了用來計算行框盒子高度的基礎高度。

(2)內聯元素的高度由固定高度和不固定高度組成,這個不固定的部分就是這裏的“行距”。換句話說,line-height之所以起作
用,就是通過改變“行距”來實現的。在CSS中,“行距”分散在當前文字的上方和下方,也就是即使是第一行文字,其上方也是
有“行距”的,只不過這個“行距”的高度僅僅是完整“行距”高度的一半,因此,也被稱爲“半行距”。

(3)行距=line-height-font-size。

(4)border以及line-height等傳統CSS屬性並沒有小數像素的概念。如果標註的是文字上邊距,則向下取整;如果是文字下
邊距,則向上取整。

(5)對於純文本元素,line-height直接決定了最終的高度。但是,如果同時有替換元素,則line-height只能決定最小高度。

(6)對於塊級元素,line-height對其本身是沒有任何作用的,我們平時改變line-height,塊級元素的高度跟着變化實際上是
通過改變塊級元素裏面內聯級別元素佔據的高度實現的。

(7)line-height的默認值是normal,還支持數值、百分比值以及長度值。爲數值類型時,其最終的計算值是和當前font-si
ze相乘後的值。爲百分比值時,其最終的計算值是和當前font-size相乘後的值。爲長度值時原意不變。

(8)如果使用數值作爲line-height的屬性值,那麼所有的子元素繼承的都是這個值;但是,如果使用百分比值或者長度值作爲
屬性值,那麼所有的子元素繼承的是最終的計算值。

(9)無論內聯元素line-height如何設置,最終父級元素的高度都是由數值大的那個line-height決定的。

(10)只要有“內聯盒子”在,就一定會有“行框盒子”,就是每一行內聯元素外面包裹的一層看不見的盒子。然後,重點來了,在每個
“行框盒子”前面有一個寬度爲0的具有該元素的字體和行高屬性的看不見的“幽靈空白節點”。

81.vertical-align 的特殊性?

(1)vertical-align的默認值是baseline,即基線對齊,而基線的定義是字母x的下邊緣。因此,內聯元素默認都是沿着字
母x的下邊緣對齊的。對於圖片等替換元素,往往使用元素本身的下邊緣作爲基線。:一個inline-block元素,如果裏面
沒有內聯元素,或者overflow不是visible,則該元素的基線就是其margin底邊緣;否則其基線就是元素裏面最後一行
內聯元素的基線。

(2)vertical-align:top就是垂直上邊緣對齊,如果是內聯元素,則和這一行位置最高的內聯元素的頂部對齊;如果display
計算值是table-cell的元素,我們不妨腦補成<td>元素,則和<tr>元素上邊緣對齊。

(3)vertical-align:middle是中間對齊,對於內聯元素,元素的垂直中心點和行框盒子基線往上1/2x-height處對齊。對
於table-cell元素,單元格填充盒子相對於外面的表格行居中對齊。

(4)vertical-align支持數值屬性,根據數值的不同,相對於基線往上或往下偏移,如果是負值,往下偏移,如果是正值,往上
偏移。

(5)vertical-align屬性的百分比值則是相對於line-height的計算值計算的。

(6)vertical-align起作用是有前提條件的,這個前提條件就是:只能應用於內聯元素以及display值爲table-cell的元
素。

(7)table-cell元素設置vertical-align垂直對齊的是子元素,但是其作用的並不是子元素,而是table-cell元素自身。

82.overflow 的特殊性?

(1)一個設置了overflow:hidden聲明的元素,假設同時存在border屬性和padding屬性,則當子元素內容超出容器寬度
高度限制的時候,剪裁的邊界是borderbox的內邊緣,而非paddingbox的內邊緣。

(2)HTML中有兩個標籤是默認可以產生滾動條的,一個是根元素<html>,另一個是文本域<textarea>。

(3)滾動條會佔用容器的可用寬度或高度。

(4)元素設置了overflow:hidden聲明,裏面內容高度溢出的時候,滾動依然存在,僅僅滾動條不存在!

83.無依賴絕對定位是什麼?

沒有設置left/top/right/bottom屬性值的絕對定位稱爲“無依賴絕對定位”。

無依賴絕對定位其定位的位置和沒有設置position:absolute時候的位置相關。

84.absolute 與 overflow 的關係?

(1)如果overflow不是定位元素,同時絕對定位元素和overflow容器之間也沒有定位元素,則overflow無法對absolute
元素進行剪裁。

(2)如果overflow的屬性值不是hidden而是auto或者scroll,即使絕對定位元素高寬比overflow元素高寬還要大,也
都不會出現滾動條。

(3)overflow元素自身transform的時候,Chrome和Opera瀏覽器下的overflow剪裁是無效的。

85.clip 裁剪是什麼?

所謂“可訪問性隱藏”,指的是雖然內容肉眼看不見,但是其他輔助設備卻能夠進行識別和訪問的隱藏。

clip剪裁被我稱爲“最佳可訪問性隱藏”的另外一個原因就是,它具有更強的普遍適應性,任何元素、任何場景都可以無障礙使用。

86.relative 的特殊性?

(1)相對定位元素的left/top/right/bottom的百分比值是相對於包含塊計算的,而不是自身。注意,雖然定位位移是相對自身,但是百分比值的計算值不是。

(2)top和bottom這兩個垂直方向的百分比值計算跟height的百分比值是一樣的,都是相對高度計算的。同時,如果包含塊的高度是auto,那麼計算值是0,偏移無效,也就是說,如果父元素沒有設定高度或者不是“格式化高度”,那麼relative類似top:20%的代碼等同於top:0。

(3)當相對定位元素同時應用對立方向定位值的時候,也就是top/bottom和left/right同時使用的時候,只有一個方向的定位屬性會起作用。而誰起作用則是與文檔流的順序有關的,默認的文檔流是自上而下、從左往右,因此top/bottom同時使用的時候,bottom失效;left/right同時使用的時候,right失效。

87.什麼是層疊上下文?

層疊上下文,英文稱作stackingcontext,是HTML中的一個三維的概念。如果一個元素含有層疊上下文,我們可以理解爲這個元
素在z軸上就“高人一等”。

層疊上下文元素有如下特性:

(1)層疊上下文的層疊水平要比普通元素高(原因後面會說明)。
(2)層疊上下文可以阻斷元素的混合模式。
(3)層疊上下文可以嵌套,內部層疊上下文及其所有子元素均受制於外部的“層疊上下文”。
(4)每個層疊上下文和兄弟元素獨立,也就是說,當進行層疊變化或渲染的時候,只需要考慮後代元素。
(5)每個層疊上下文是自成體系的,當元素髮生層疊的時候,整個元素被認爲是在父層疊上下文的層疊順序中。


層疊上下文的創建:

(1)頁面根元素天生具有層疊上下文,稱爲根層疊上下文。根層疊上下文指的是頁面根元素,可以看成是<html>元素。因此,頁面中所有的元素一定處於至少一個“層疊結界”中。

(2)對於position值爲relative/absolute以及Firefox/IE瀏覽器(不包括Chrome瀏覽器)下含有position:fixed聲明的定位元素,當其z-index值不是auto的時候,會創建層疊上下文。Chrome等WebKit內核瀏覽器下,position:fixed元素天然層疊上下文元素,無須z-index爲數值。根據我的測試,目前IE和Firefox仍是老套路。

(3)其他一些CSS3屬性,比如元素的opacity值不是1。

88.什麼是層疊水平?

層疊水平,英文稱作stackinglevel,決定了同一個層疊上下文中元素在z軸上的顯示順序。

顯而易見,所有的元素都有層疊水平,包括層疊上下文元素,也包括普通元素。然而,對普通元素的層疊水平探討只侷限在當前層疊上
下文元素中。

89.元素的層疊順序?

層疊順序,英文稱作 stackingorder,表示元素髮生層疊時有着特定的垂直顯示順序。

層疊順序

90.層疊準則?

(1)誰大誰上:當具有明顯的層疊水平標識的時候,如生效的z-index屬性值,在同一個層疊上下文領域,層疊水平值大的那一個覆蓋小的那一個。

(2)後來居上:當元素的層疊水平一致、層疊順序相同的時候,在DOM流中處於後面的元素會覆蓋前面的元素。

91.font-weight 的特殊性?

如果使用數值作爲font-weight屬性值,必須是100~900的整百數。因爲這裏的數值僅僅是外表長得像數值,實際上是一個具有特定含義的關鍵字,並且這裏的數值關鍵字和字母關鍵字之間是有對應關係的。

92.text-indent 的特殊性?

(1)text-indent僅對第一行內聯盒子內容有效。

(2)非替換元素以外的display計算值爲inline的內聯元素設置text-indent值無效,如果計算值inline-block/inli
ne-table則會生效。

(3)<input>標籤按鈕text-indent值無效。

(4)<button>標籤按鈕text-indent值有效。

(5)text-indent的百分比值是相對於當前元素的“包含塊”計算的,而不是當前元素。

93.letter-spacing 與字符間距?

letter-spacing可以用來控制字符之間的間距,這裏說的“字符”包括英文字母、漢字以及空格等。

letter-spacing具有以下一些特性。

(1)繼承性。
(2)默認值是normal而不是0。雖然說正常情況下,normal的計算值就是0,但兩者還是有差別的,在有些場景下,letter-spacing會調整normal的計算值以實現更好的版面佈局。
(3)支持負值,且值足夠大的時候,會讓字符形成重疊,甚至反向排列。
(4)和text-indent屬性一樣,無論值多大或多小,第一行一定會保留至少一個字符。
(5)支持小數值,即使0.1px也是支持的。
(6)暫不支持百分比值。

94.word-spacing 與單詞間距?

letter-spacing作用於所有字符,但word-spacing僅作用於空格字符。換句話說,word-spacing的作用就是增加空格的間隙
寬度。

95.white-space 與換行和空格的控制?

white-space屬性聲明瞭如何處理元素內的空白字符,這類空白字符包括Space(空格)鍵、Enter(回車)鍵、Tab(製表符)
鍵產生的空白。因此,white-space可以決定圖文內容是否在一行顯示(回車空格是否生效),是否顯示大段連續空白(空格是否
生效)等。

其屬性值包括下面這些。
•normal:合併空白字符和換行符。
•pre:空白字符不合並,並且內容只在有換行符的地方換行。
•nowrap:該值和normal一樣會合並空白字符,但不允許文本環繞。
•pre-wrap:空白字符不合並,並且內容只在有換行符的地方換行,同時允許文本環繞。
•pre-line:合併空白字符,但只在有換行符的地方換行,允許文本環繞。

96.隱藏元素的 background-image 到底加不加載?

相關知識點:

根據測試,一個元素如果display計算值爲none,在IE瀏覽器下(IE8~IE11,更高版本不確定)依然會發送圖片請求,Fire
fox瀏覽器不會,至於Chrome和Safari瀏覽器則似乎更加智能一點:如果隱藏元素同時又設置了background-image,則圖片
依然會去加載;如果是父元素的display計算值爲none,則背景圖不會請求,此時瀏覽器或許放心地認爲這個背景圖暫時是不會使
用的。

如果不是background-image,而是<img>元素,則設置display:none在所有瀏覽器下依舊都會請求圖片資源。

還需要注意的是如果設置的樣式沒有對應的元素,則background-image也不會加載。hover情況下的background-image,在觸
發時加載。

回答:

-(1)元素的背景圖片

-元素本身設置 display:none,會請求圖片 -父級元素設置 display:none,不會請求圖片 -樣式沒有元素使用,不會請求 -:hover 樣式下,觸發時請求

-(2)img 標籤圖片任何情況下都會請求圖片

詳細資料可以參考: 《CSS 控制前端圖片 HTTP 請求的各種情況示例》

97.如何實現單行/多行文本溢出的省略(…)?

/*單行文本溢出*/
p {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/*多行文本溢出*/
p {
  position: relative;
  line-height: 1.5em;
  /*高度爲需要顯示的行數*行高,比如這裏我們顯示兩行,則爲3*/
  height: 3em;
  overflow: hidden;
}

p:after {
  content: "...";
  position: absolute;
  bottom: 0;
  right: 0;
  background-color: #fff;
}

詳細資料可以參考: 《【CSS/JS】如何實現單行/多行文本溢出的省略》 《CSS 多行文本溢出省略顯示》

98.常見的元素隱藏方式?

-(1)使用 display:none;隱藏元素,渲染樹不會包含該渲染對象,因此該元素不會在頁面中佔據位置,也不會響應綁定的監聽事件。

-(2)使用 visibility:hidden;隱藏元素。元素在頁面中仍佔據空間,但是不會響應綁定的監聽事件。

-(3)使用 opacity:0;將元素的透明度設置爲 0,以此來實現元素的隱藏。元素在頁面中仍然佔據空間,並且能夠響應元素綁定的監聽事件。

-(4)通過使用絕對定位將元素移除可視區域內,以此來實現元素的隱藏。

-(5)通過 z-index 負值,來使其他元素遮蓋住該元素,以此來實現隱藏。

-(6)通過 clip/clip-path 元素裁剪的方法來實現元素的隱藏,這種方法下,元素仍在頁面中佔據位置,但是不會響應綁定的監聽事件。

-(7)通過 transform:scale(0,0)來將元素縮放爲 0,以此來實現元素的隱藏。這種方法下,元素仍在頁面中佔據位置,但是不會響應綁定的監聽事件。

詳細資料可以參考: 《CSS 隱藏元素的八種方法》

99.css 實現上下固定中間自適應佈局?

利用絕對定位實現body {
  padding: 0;
  margin: 0;
}

.header {
  position: absolute;
  top: 0;
  width: 100%;
  height: 100px;
  background: red;
}

.container {
  position: absolute;
  top: 100px;
  bottom: 100px;
  width: 100%;
  background: green;
}

.footer {
  position: absolute;
  bottom: 0;
  height: 100px;
  width: 100%;
  background: red;
}

利用flex佈局實現html,
body {
  height: 100%;
}

body {
  display: flex;
  padding: 0;
  margin: 0;
  flex-direction: column;
}

.header {
  height: 100px;
  background: red;
}

.container {
  flex-grow: 1;
  background: green;
}

.footer {
  height: 100px;
  background: red;
}

詳細資料可以參考: 《css 實現上下固定中間自適應佈局》

100.css 兩欄佈局的實現?

相關資料:

/*兩欄佈局一般指的是頁面中一共兩欄,左邊固定,右邊自適應的佈局,一共有四種實現的方式。*/
/*以左邊寬度固定爲200px爲例*/

/*(1)利用浮動,將左邊元素寬度設置爲200px,並且設置向左浮動。將右邊元素的margin-left設置爲200px,寬度設置爲auto(默認爲auto,撐滿整個父元素)。*/
.outer {
  height: 100px;
}

.left {
  float: left;

  height: 100px;
  width: 200px;

  background: tomato;
}

.right {
  margin-left: 200px;

  width: auto;
  height: 100px;

  background: gold;
}

/*(2)第二種是利用flex佈局,將左邊元素的放大和縮小比例設置爲0,基礎大小設置爲200px。將右邊的元素的放大比例設置爲1,縮小比例設置爲1,基礎大小設置爲auto。*/
.outer {
  display: flex;

  height: 100px;
}

.left {
  flex-shrink: 0;
  flex-grow: 0;
  flex-basis: 200px;

  background: tomato;
}

.right {
  flex: auto;
  /*11auto*/

  background: gold;
}

/*(3)第三種是利用絕對定位佈局的方式,將父級元素設置相對定位。左邊元素設置爲absolute定位,並且寬度設置爲
200px。將右邊元素的margin-left的值設置爲200px。*/
.outer {
  position: relative;

  height: 100px;
}

.left {
  position: absolute;

  width: 200px;
  height: 100px;

  background: tomato;
}

.right {
  margin-left: 200px;
  height: 100px;

  background: gold;
}

/*(4)第四種還是利用絕對定位的方式,將父級元素設置爲相對定位。左邊元素寬度設置爲200px,右邊元素設置爲絕對定位,左邊定位爲200px,其餘方向定位爲0。*/
.outer {
  position: relative;

  height: 100px;
}

.left {
  width: 200px;
  height: 100px;

  background: tomato;
}

.right {
  position: absolute;

  top: 0;
  right: 0;
  bottom: 0;
  left: 200px;

  background: gold;
}

《兩欄佈局 demo 展示》

回答:

兩欄佈局一般指的是頁面中一共兩欄,左邊固定,右邊自適應的佈局,一共有四種實現的方式。

以左邊寬度固定爲 200px 爲例

-(1)利用浮動,將左邊元素寬度設置爲 200px,並且設置向左浮動。將右邊元素的 margin-left 設置爲 200px,寬度設置爲 auto(默認爲 auto,撐滿整個父元素)。

-(2)第二種是利用 flex 佈局,將左邊元素的放大和縮小比例設置爲 0,基礎大小設置爲 200px。將右邊的元素的放大比例設置爲 1,縮小比例設置爲 1,基礎大小設置爲 auto。

-(3)第三種是利用絕對定位佈局的方式,將父級元素設置相對定位。左邊元素設置爲 absolute 定位,並且寬度設置爲 200px。將右邊元素的 margin-left 的值設置爲 200px。

-(4)第四種還是利用絕對定位的方式,將父級元素設置爲相對定位。左邊元素寬度設置爲 200px,右邊元素設置爲絕對定位,左邊定位爲 200px,其餘方向定位爲 0。

101.css 三欄佈局的實現?

相關資料:

/*三欄佈局一般指的是頁面中一共有三欄,左右兩欄寬度固定,中間自適應的佈局,一共有五種實現方式。

這裏以左邊寬度固定爲100px,右邊寬度固定爲200px爲例。*/

/*(1)利用絕對定位的方式,左右兩欄設置爲絕對定位,中間設置對應方向大小的margin的值。*/
.outer {
  position: relative;
  height: 100px;
}

.left {
  position: absolute;

  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  position: absolute;
  top: 0;
  right: 0;

  width: 200px;
  height: 100px;
  background: gold;
}

.center {
  margin-left: 100px;
  margin-right: 200px;
  height: 100px;
  background: lightgreen;
}

/*(2)利用flex佈局的方式,左右兩欄的放大和縮小比例都設置爲0,基礎大小設置爲固定的大小,中間一欄設置爲auto*/
.outer {
  display: flex;
  height: 100px;
}

.left {
  flex: 00100px;
  background: tomato;
}

.right {
  flex: 00200px;
  background: gold;
}

.center {
  flex: auto;
  background: lightgreen;
}

/*(3)利用浮動的方式,左右兩欄設置固定大小,並設置對應方向的浮動。中間一欄設置左右兩個方向的margin值,注意這種方式,中間一欄必須放到最後。*/
.outer {
  height: 100px;
}

.left {
  float: left;
  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  float: right;
  width: 200px;
  height: 100px;
  background: gold;
}

.center {
  height: 100px;
  margin-left: 100px;
  margin-right: 200px;
  background: lightgreen;
}

/*(4)雙飛翼佈局,利用浮動和負邊距來實現。父級元素設置左右的pedding,三列均設置向左浮動,中間一列放在最前面,寬度設置爲父級元素的寬度,因此後面兩列都被擠到了下一行,通過設置margin負值將其移動到上一行,再利用相對定位,定位到兩邊。*/
.outer {
  height: 100px;
  padding-left: 100px;
  padding-right: 200px;
}

.left {
  position: relative;
  left: -100px;

  float: left;
  margin-left: -100%;

  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  position: relative;
  left: 200px;

  float: right;
  margin-left: -200px;

  width: 200px;
  height: 100px;
  background: gold;
}

.center {
  float: left;

  width: 100%;
  height: 100px;
  background: lightgreen;
}

/*(5)雙飛翼佈局,雙飛翼佈局相對於聖盃佈局來說,左右位置的保留是通過中間列的margin值來實現的,而不是通過父元
素的pedding來實現的。本質上來說,也是通過浮動和外邊距負值來實現的。*/

.outer {
  height: 100px;
}

.left {
  float: left;
  margin-left: -100%;

  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  float: left;
  margin-left: -200px;

  width: 200px;
  height: 100px;
  background: gold;
}

.wrapper {
  float: left;

  width: 100%;
  height: 100px;
  background: lightgreen;
}

.center {
  margin-left: 100px;
  margin-right: 200px;
  height: 100px;
}

《三欄佈局 demo 展示》

回答:

三欄佈局一般指的是頁面中一共有三欄,左右兩欄寬度固定,中間自適應的佈局,一共有五種實現方式。

這裏以左邊寬度固定爲100px,右邊寬度固定爲200px爲例。

(1)利用絕對定位的方式,左右兩欄設置爲絕對定位,中間設置對應方向大小的margin的值。

(2)利用flex佈局的方式,左右兩欄的放大和縮小比例都設置爲0,基礎大小設置爲固定的大小,中間一欄設置爲auto。

(3)利用浮動的方式,左右兩欄設置固定大小,並設置對應方向的浮動。中間一欄設置左右兩個方向的margin值,注意這種方式,中間一欄必須放到最後。

(4)聖盃佈局,利用浮動和負邊距來實現。父級元素設置左右的pedding,三列均設置向左浮動,中間一列放在最前面,寬度設置爲父級元素的寬度,因此後面兩列都被擠到了下一行,通過設置margin負值將其移動到上一行,再利用相對定位,定位到兩邊。雙飛翼佈局中間列的寬度不能小於兩邊任意列的寬度,而雙飛翼佈局則不存在這個問題。

(5)雙飛翼佈局,雙飛翼佈局相對於聖盃佈局來說,左右位置的保留是通過中間列的margin值來實現的,而不是通過父元素的pedding來實現的。本質上來說,也是通過浮動和外邊距負值來實現的。

102.實現一個寬高自適應的正方形

/*1.第一種方式是利用vw來實現*/
.square {
  width: 10%;
  height: 10vw;
  background: tomato;
}

/*2.第二種方式是利用元素的margin/padding百分比是相對父元素width的性質來實現*/
.square {
  width: 20%;
  height: 0;
  padding-top: 20%;
  background: orange;
}

/*3.第三種方式是利用子元素的margin-top的值來實現的*/
.square {
  width: 30%;
  overflow: hidden;
  background: yellow;
}

.square::after {
  content: "";
  display: block;
  margin-top: 100%;
}

《自適應正方形 demo 展示》

103.實現一個三角形

/*三角形的實現原理是利用了元素邊框連接處的等分原理。*/
.triangle {
  width: 0;
  height: 0;
  border-width: 100px;
  border-style: solid;
  border-color: tomatotransparenttransparenttransparent;
}

《三角形 demo 展示》

104.一個自適應矩形,水平垂直居中,且寬高比爲 2:1

/*實現原理參考自適應正方形和水平居中方式*/
.box {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  margin: auto;

  width: 10%;
  height: 0;
  padding-top: 20%;
  background: tomato;
}

JavaScript 面試知識點總結

本部分主要是筆者在複習 JavaScript 相關知識和一些相關面試題時所做的筆記,如果出現錯誤,希望大家指出!

目錄

1. 介紹 js 的基本數據類型。

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

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

涉及知識點:

棧:原始數據類型(Undefined、Null、Boolean、Number、String)
堆:引用數據類型(對象、數組和函數)

兩種類型的區別是:存儲位置不同。
原始數據類型直接存儲在棧(stack)中的簡單數據段,佔據空間小、大小固定,屬於被頻繁使用數據,所以放入棧中存儲。

引用數據類型存儲在堆(heap)中的對象,佔據空間大、大小不固定。如果存儲在棧中,將會影響程序運行的性能;引用數據類型在
棧中存儲了指針,該指針指向堆中該實體的起始地址。當解釋器尋找引用值時,會首先檢索其在棧中的地址,取得地址後從堆中獲得實
體。

回答:

js 可以分爲兩種類型的值,一種是基本數據類型,一種是複雜數據類型。

基本數據類型....(參考1)

複雜數據類型指的是 Object 類型,所有其他的如 Array、Date 等數據類型都可以理解爲 Object 類型的子類。

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

詳細資料可以參考: 《JavaScript 有幾種類型的值?》 《JavaScript 有幾種類型的值?能否畫一下它們的內存圖;》

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

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

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

在操作系統中,內存被分爲棧區和堆區。

棧區內存由編譯器自動分配釋放,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。

堆區內存一般由程序員分配釋放,若程序員不釋放,程序結束時可能由垃圾回收機制回收。

詳細資料可以參考: 《什麼是堆?什麼是棧?他們之間有什麼區別和聯繫?》

4. 內部屬性 [[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]"

5. 介紹 js 有哪些內置對象?

涉及知識點:

全局的對象( global objects )或稱標準內置對象,不要和 "全局對象(global object)" 混淆。這裏說的全局的對象是說在
全局作用域裏的對象。全局作用域中的其他對象可以由用戶的腳本創建或由宿主程序提供。

標準內置對象的分類

(1)值屬性,這些全局屬性返回一個簡單值,這些值沒有自己的屬性和方法。
     
    例如 Infinity、NaN、undefined、null 字面量

(2)函數屬性,全局函數可以直接調用,不需要在調用時指定所屬對象,執行結束後會將結果直接返回給調用者。

    例如 eval()、parseFloat()、parseInt() 等
 
(3)基本對象,基本對象是定義或使用其他對象的基礎。基本對象包括一般對象、函數對象和錯誤對象。
     
    例如 Object、Function、Boolean、Symbol、Error 等

(4)數字和日期對象,用來表示數字、日期和執行數學計算的對象。

    例如 Number、Math、Date 

(5)字符串,用來表示和操作字符串的對象。
    
    例如 String、RegExp

(6)可索引的集合對象,這些對象表示按照索引值來排序的數據集合,包括數組和類型數組,以及類數組結構的對象。例如 Array

(7)使用鍵的集合對象,這些集合對象在存儲數據時會使用到鍵,支持按照插入順序來迭代元素。
     
    例如 Map、Set、WeakMap、WeakSet
 
(8)矢量集合,SIMD 矢量集合中的數據會被組織爲一個數據序列。

    例如 SIMD 等

(9)結構化數據,這些對象用來表示和操作結構化的緩衝區數據,或使用 JSON 編碼的數據。

    例如 JSON 等

(10)控制抽象對象

    例如 Promise、Generator 等

(11)反射

    例如 Reflect、Proxy

(12)國際化,爲了支持多語言處理而加入 ECMAScript 的對象。

    例如 Intl、Intl.Collator 等

(13)WebAssembly

(14)其他

     例如 arguments

回答:

js 中的內置對象主要指的是在程序執行前存在全局作用域裏的由 js 定義的一些全局值屬性、函數和用來實例化其他對象的構造函
數對象。一般我們經常用到的如全局變量值 NaN、undefined,全局函數如 parseInt()、parseFloat() 用來實例化對象的構
造函數如 Date、Object 等,還有提供數學計算的單體內置對象如 Math 對象。

詳細資料可以參考: 《標準內置對象的分類》 《JS 所有內置對象屬性和方法彙總》

6. undefined 與 undeclared 的區別?

已在作用域中聲明但還沒有賦值的變量,是 undefined 的。相反,還沒有在作用域中聲明過的變量,是 undeclared 的。

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

7. null 和 undefined 的區別?

首先 Undefined 和 Null 都是基本數據類型,這兩個基本數據類型分別都只有一個值,就是 undefined 和 null。

undefined 代表的含義是未定義,null 代表的含義是空對象。一般變量聲明瞭但還沒有定義的時候會返回 undefined,null
主要用於賦值給一些可能會返回對象的變量,作爲初始化。

undefined 在 js 中不是一個保留字,這意味着我們可以使用 undefined 來作爲一個變量名,這樣的做法是非常危險的,它
會影響我們對 undefined 值的判斷。但是我們可以通過一些方法獲得安全的 undefined 值,比如說 void 0。

當我們對兩種類型使用 typeof 進行判斷的時候,Null 類型化會返回 “object”,這是一個歷史遺留的問題。當我們使用雙等
號對兩種類型的值進行比較時會返回 true,使用三個等號時會返回 false。

詳細資料可以參考: 《JavaScript 深入理解之 undefined 與 null》

8. 如何獲取安全的 undefined 值?

因爲 undefined 是一個標識符,所以可以被當作變量來使用和賦值,但是這樣會影響 undefined 的正常判斷。

表達式 void ___ 沒有返回值,因此返回結果是 undefined。void 並不改變表達式的結果,只是讓表達式不返回值。

按慣例我們用 void 0 來獲得 undefined。

9. 說幾條寫 JavaScript 的基本規範?

在平常項目開發中,我們遵守一些這樣的基本規範,比如說:

(1)一個函數作用域中所有的變量聲明應該儘量提到函數首部,用一個 var 聲明,不允許出現兩個連續的 var 聲明,聲明時
    如果變量沒有值,應該給該變量賦值對應類型的初始值,便於他人閱讀代碼時,能夠一目瞭然的知道變量對應的類型值。

(2)代碼中出現地址、時間等字符串時需要使用常量代替。

(3)在進行比較的時候吧,儘量使用'===', '!=='代替'==', '!='。

(4)不要在內置對象的原型上添加方法,如 Array, Date。

(5)switch 語句必須帶有 default 分支。

(6)for 循環必須使用大括號。

(7)if 語句必須使用大括號。

10. JavaScript 原型,原型鏈? 有什麼特點?

 在 js 中我們是使用構造函數來新建一個對象的,每一個構造函數的內部都有一個 prototype 屬性值,這個屬性值是一個對
 象,這個對象包含了可以由該構造函數的所有實例共享的屬性和方法。當我們使用構造函數新建一個對象後,在這個對象的內部
 將包含一個指針,這個指針指向構造函數的 prototype 屬性對應的值,在 ES5 中這個指針被稱爲對象的原型。一般來說我們
 是不應該能夠獲取到這個值的,但是現在瀏覽器中都實現了 __proto__ 屬性來讓我們訪問這個屬性,但是我們最好不要使用這
 個屬性,因爲它不是規範中規定的。ES5 中新增了一個 Object.getPrototypeOf() 方法,我們可以通過這個方法來獲取對
 象的原型。

 當我們訪問一個對象的屬性時,如果這個對象內部不存在這個屬性,那麼它就會去它的原型對象裏找這個屬性,這個原型對象又
 會有自己的原型,於是就這樣一直找下去,也就是原型鏈的概念。原型鏈的盡頭一般來說都是 Object.prototype 所以這就
 是我們新建的對象爲什麼能夠使用 toString() 等方法的原因。

 特點:

 JavaScript 對象是通過引用來傳遞的,我們創建的每個新對象實體中並沒有一份屬於自己的原型副本。當我們修改原型時,與
 之相關的對象也會繼承這一改變。

詳細資料可以參考: 《JavaScript 深入理解之原型與原型鏈》

11. js 獲取原型的方法?

 (1)p.__proto__

 (2)p.constructor.prototype

 (3)Object.getPrototypeOf(p)

12. 在 js 中不同進制數字的表示方式

 (1)以 0X、0x 開頭的表示爲十六進制。

 (2)以 0、0O、0o 開頭的表示爲八進制。

 (3)以 0B、0b 開頭的表示爲二進制格式。

13. js 中整數的安全範圍是多少?

 安全整數指的是,在這個範圍內的整數轉化爲二進制存儲的時候不會出現精度丟失,能夠被“安全”呈現的最大整數是 2^53 - 1,
 即9007199254740991,在 ES6 中被定義爲 Number.MAX_SAFE_INTEGER。最小整數是-9007199254740991,在 ES6 中
 被定義爲 Number.MIN_SAFE_INTEGER。

 如果某次計算的結果得到了一個超過 JavaScript 數值範圍的值,那麼這個值會被自動轉換爲特殊的 Infinity 值。如果某次
 計算返回了正或負的 Infinity 值,那麼該值將無法參與下一次的計算。判斷一個數是不是有窮的,可以使用 isFinite 函數
 來判斷。

14. typeof NaN 的結果是什麼?

 NaN 意指“不是一個數字”(not a number),NaN 是一個“警戒值”(sentinel value,有特殊用途的常規值),用於指出
 數字類型中的錯誤情況,即“執行數學運算沒有成功,這是失敗後返回的結果”。

 typeof NaN; // "number"

 NaN 是一個特殊值,它和自身不相等,是唯一一個非自反(自反,reflexive,即 x === x 不成立)的值。而 NaN != NaN
 爲 true。

15. isNaN 和 Number.isNaN 函數的區別?

 函數 isNaN 接收參數後,會嘗試將這個參數轉換爲數值,任何不能被轉換爲數值的的值都會返回 true,因此非數字值傳入也會
 返回 true ,會影響 NaN 的判斷。

 函數 Number.isNaN 會首先判斷傳入參數是否爲數字,如果是數字再繼續判斷是否爲 NaN ,這種方法對於 NaN 的判斷更爲
 準確。

16. Array 構造函數只有一個參數值時的表現?

 Array 構造函數只帶一個數字參數的時候,該參數會被作爲數組的預設長度(length),而非只充當數組中的一個元素。這樣
 創建出來的只是一個空數組,只不過它的 length 屬性被設置成了指定的值。

 構造函數 Array(..) 不要求必須帶 new 關鍵字。不帶時,它會被自動補上。

17. 其他值到字符串的轉換規則?

 規範的 9.8 節中定義了抽象操作 ToString ,它負責處理非字符串到字符串的強制類型轉換。

 (1)Null 和 Undefined 類型 ,null 轉換爲 "null",undefined 轉換爲 "undefined",
 
 (2)Boolean 類型,true 轉換爲 "true",false 轉換爲 "false"。
 
 (3)Number 類型的值直接轉換,不過那些極小和極大的數字會使用指數形式。

 (4)Symbol 類型的值直接轉換,但是隻允許顯式強制類型轉換,使用隱式強制類型轉換會產生錯誤。

 (3)對普通對象來說,除非自行定義 toString() 方法,否則會調用 toString()(Object.prototype.toString())
     來返回內部屬性 [[Class]] 的值,如"[object Object]"。如果對象有自己的 toString() 方法,字符串化時就會
     調用該方法並使用其返回值。

18. 其他值到數字值的轉換規則?

 有時我們需要將非數字值當作數字來使用,比如數學運算。爲此 ES5 規範在 9.3 節定義了抽象操作 ToNumber。

 (1)Undefined 類型的值轉換爲 NaN。

 (2)Null 類型的值轉換爲 0。

 (3)Boolean 類型的值,true 轉換爲 1,false 轉換爲 0。

 (4)String 類型的值轉換如同使用 Number() 函數進行轉換,如果包含非數字值則轉換爲 NaN,空字符串爲 0。

 (5)Symbol 類型的值不能轉換爲數字,會報錯。

 (6)對象(包括數組)會首先被轉換爲相應的基本類型值,如果返回的是非數字的基本類型值,則再遵循以上規則將其強制轉
     換爲數字。

     爲了將值轉換爲相應的基本類型值,抽象操作 ToPrimitive 會首先(通過內部操作 DefaultValue)檢查該值是否有
     valueOf() 方法。如果有並且返回基本類型值,就使用該值進行強制類型轉換。如果沒有就使用 toString() 的返回
     值(如果存在)來進行強制類型轉換。

     如果 valueOf() 和 toString() 均不返回基本類型值,會產生 TypeError 錯誤。

19. 其他值到布爾類型的值的轉換規則?

 ES5 規範 9.2 節中定義了抽象操作 ToBoolean,列舉了布爾強制類型轉換所有可能出現的結果。

 以下這些是假值:
     • undefined
     • null
     • false
     • +0、-0 和 NaN
     • ""

 假值的布爾強制類型轉換結果爲 false。從邏輯上說,假值列表以外的都應該是真值。

20. {} 和 [] 的 valueOf 和 toString 的結果是什麼?

 {} 的 valueOf 結果爲 {} ,toString 的結果爲 "[object Object]"

 [] 的 valueOf 結果爲 [] ,toString 的結果爲 ""

21. 什麼是假值對象?

 瀏覽器在某些特定情況下,在常規 JavaScript 語法基礎上自己創建了一些外來值,這些就是“假值對象”。假值對象看起來和
 普通對象並無二致(都有屬性,等等),但將它們強制類型轉換爲布爾值時結果爲 false 最常見的例子是 document.all,它
 是一個類數組對象,包含了頁面上的所有元素,由 DOM(而不是 JavaScript 引擎)提供給 JavaScript 程序使用。

22. ~ 操作符的作用?

 ~ 返回 2 的補碼,並且 ~ 會將數字轉換爲 32 位整數,因此我們可以使用 ~ 來進行取整操作。

 ~x 大致等同於 -(x+1)。

23. 解析字符串中的數字和將字符串強制類型轉換爲數字的返回結果都是數字,它們之間的區別是什麼?

 解析允許字符串(如 parseInt() )中含有非數字字符,解析按從左到右的順序,如果遇到非數字字符就停止。而轉換(如 Nu
 mber ())不允許出現非數字字符,否則會失敗並返回 NaN。

24. + 操作符什麼時候用於字符串的拼接?

 根據 ES5 規範 11.6.1 節,如果某個操作數是字符串或者能夠通過以下步驟轉換爲字符串的話,+ 將進行拼接操作。如果其
 中一個操作數是對象(包括數組),則首先對其調用 ToPrimitive 抽象操作,該抽象操作再調用 [[DefaultValue]],以
 數字作爲上下文。如果不能轉換爲字符串,則會將其轉換爲數字類型來進行計算。

 簡單來說就是,如果 + 的其中一個操作數是字符串(或者通過以上步驟最終得到字符串),則執行字符串拼接,否則執行數字
 加法。

 那麼對於除了加法的運算符來說,只要其中一方是數字,那麼另一方就會被轉爲數字。

25. 什麼情況下會發生布爾值的隱式強制類型轉換?

 (1) if (..) 語句中的條件判斷表達式。
 (2) for ( .. ; .. ; .. ) 語句中的條件判斷表達式(第二個)。
 (3) while (..) 和 do..while(..) 循環中的條件判斷表達式。
 (4) ? : 中的條件判斷表達式。
 (5) 邏輯運算符 ||(邏輯或)和 &&(邏輯與)左邊的操作數(作爲條件判斷表達式)。

26. || 和 && 操作符的返回值?

 || 和 && 首先會對第一個操作數執行條件判斷,如果其不是布爾值就先進行 ToBoolean 強制類型轉換,然後再執行條件
 判斷。

 對於 || 來說,如果條件判斷結果爲 true 就返回第一個操作數的值,如果爲 false 就返回第二個操作數的值。

 && 則相反,如果條件判斷結果爲 true 就返回第二個操作數的值,如果爲 false 就返回第一個操作數的值。

 || 和 && 返回它們其中一個操作數的值,而非條件判斷的結果 

27. Symbol 值的強制類型轉換?

 ES6 允許從符號到字符串的顯式強制類型轉換,然而隱式強制類型轉換會產生錯誤。

 Symbol 值不能夠被強制類型轉換爲數字(顯式和隱式都會產生錯誤),但可以被強制類型轉換爲布爾值(顯式和隱式結果
 都是 true )。

28. == 操作符的強制類型轉換規則?

 (1)字符串和數字之間的相等比較,將字符串轉換爲數字之後再進行比較。

 (2)其他類型和布爾類型之間的相等比較,先將布爾值轉換爲數字後,再應用其他規則進行比較。

 (3)null 和 undefined 之間的相等比較,結果爲真。其他值和它們進行比較都返回假值。

 (4)對象和非對象之間的相等比較,對象先調用 ToPrimitive 抽象操作後,再進行比較。
 
 (5)如果一個操作值爲 NaN ,則相等比較返回 false( NaN 本身也不等於 NaN )。

 (6)如果兩個操作值都是對象,則比較它們是不是指向同一個對象。如果兩個操作數都指向同一個對象,則相等操作符返回
     true,否則,返回 false。

詳細資料可以參考: 《JavaScript 字符串間的比較》

29. 如何將字符串轉化爲數字,例如 ‘12.3b’?

 (1)使用 Number() 方法,前提是所包含的字符串不包含不合法字符。

 (2)使用 parseInt() 方法,parseInt() 函數可解析一個字符串,並返回一個整數。還可以設置要解析的數字的基數。
     當基數的值爲 0,或沒有設置該參數時,parseInt() 會根據 string 來判斷數字的基數。

 (3)使用 parseFloat() 方法,該函數解析一個字符串參數並返回一個浮點數。

 (4)使用 + 操作符的隱式轉換。

詳細資料可以參考: 《詳解 JS 中 Number()、parseInt() 和 parseFloat() 的區別》

30. 如何將浮點數點左邊的數每三位添加一個逗號,如12000000.11轉化爲『12,000,000.11』?

 function format(number){
      return number && number.replace(/(?!^)(?=(\d{3})+\.)/g,",")
 }

31. 常用正則表達式

 (1)匹配 16 進制顏色值
     var regex = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;

 (2)匹配日期,如 yyyy-mm-dd 格式
     var regex = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;

 (3)匹配 qq 號
     var regex = /^[1-9][0-9]{4,10}$/g;

 (4)手機號碼正則
     var regex = /^1[34578]\d{9}$/g;

 (5)用戶名正則
     var regex = /^[a-zA-Z\$][a-zA-Z0-9_\$]{4,16}$/;

詳細資料可以參考: 《前端表單驗證常用的15個 JS 正則表達式》 《JS 常用正則彙總》

32. 生成隨機數的各種方法?

《JS - 生成隨機數的方法彙總(不同範圍、類型的隨機數)》

33. 如何實現數組的隨機排序?

 (1)使用數組 sort 方法對數組元素隨機排序,讓 Math.random() 出來的數與 0.5 比較,如果大於就返回 1 交換位
     置,如果小於就返回 -1,不交換位置。

     function randomSort(a, b) { 
       return Math.random() > 0.5 ? -1 : 1; 
     }
     
     缺點:每個元素被派到新數組的位置不是隨機的,原因是 sort() 方法是依次比較的。

 
 (2)隨機從原數組抽取一個元素,加入到新數組

     function randomSort(arr) {
         var result = [];

         while (arr.length > 0) {
             var randomIndex = Math.floor(Math.random() * arr.length);
             result.push(arr[randomIndex]);
             arr.splice(randomIndex, 1);
         }

         return result;
     }

  (3)隨機交換數組內的元素(洗牌算法類似)

      function randomSort(arr) {
       var index,
         randomIndex,
         temp,
         len = arr.length;

       for (index = 0; index < len; index++) {
         randomIndex = Math.floor(Math.random() * (len - index)) + index;

         temp = arr[index];
         arr[index] = arr[randomIndex];
         arr[randomIndex] = temp;
       }

       return arr;
     }
     
     // es6
     function randomSort(array) {
       let length = array.length;

       if (!Array.isArray(array) || length <= 1) return;

       for (let index = 0; index < length - 1; index++) {
         let randomIndex = Math.floor(Math.random() * (length - index)) + index;

         [array[index], array[randomIndex]] = [array[randomIndex], array[index]];
       }

       return array;
     }

詳細資料可以參考: 《Fisher and Yates 的原始版》 《javascript 實現數組隨機排序?》 《JavaScript 學習筆記:數組隨機排序》

34. javascript 創建對象的幾種方式?

 我們一般使用字面量的形式直接創建對象,但是這種創建方式對於創建大量相似對象的時候,會產生大量的重複代碼。但 js
 和一般的面向對象的語言不同,在 ES6 之前它沒有類的概念。但是我們可以使用函數來進行模擬,從而產生出可複用的對象
 創建方式,我瞭解到的方式有這麼幾種:

 (1)第一種是工廠模式,工廠模式的主要工作原理是用函數來封裝創建對象的細節,從而通過調用函數來達到複用的目的。但
     是它有一個很大的問題就是創建出來的對象無法和某個類型聯繫起來,它只是簡單的封裝了複用代碼,而沒有建立起對象
     和類型間的關係。

 (2)第二種是構造函數模式。js 中每一個函數都可以作爲構造函數,只要一個函數是通過 new 來調用的,那麼我們就可以
     把它稱爲構造函數。執行構造函數首先會創建一個對象,然後將對象的原型指向構造函數的 prototype 屬性,然後將執
     行上下文中的 this 指向這個對象,最後再執行整個函數,如果返回值不是對象,則返回新建的對象。因爲 this 的值
     指向了新建的對象,因此我們可以使用 this 給對象賦值。構造函數模式相對於工廠模式的優點是,所創建的對象和構造
     函數建立起了聯繫,因此我們可以通過原型來識別對象的類型。但是構造函數存在一個缺點就是,造成了不必要的函數對
     象的創建,因爲在 js 中函數也是一個對象,因此如果對象屬性中如果包含函數的話,那麼每次我們都會新建一個函數對
     象,浪費了不必要的內存空間,因爲函數是所有的實例都可以通用的。

 (3)第三種模式是原型模式,因爲每一個函數都有一個 prototype 屬性,這個屬性是一個對象,它包含了通過構造函數創
     建的所有實例都能共享的屬性和方法。因此我們可以使用原型對象來添加公用屬性和方法,從而實現代碼的複用。這種方
     式相對於構造函數模式來說,解決了函數對象的複用問題。但是這種模式也存在一些問題,一個是沒有辦法通過傳入參數
     來初始化值,另一個是如果存在一個引用類型如 Array 這樣的值,那麼所有的實例將共享一個對象,一個實例對引用類
     型值的改變會影響所有的實例。

 (4)第四種模式是組合使用構造函數模式和原型模式,這是創建自定義類型的最常見方式。因爲構造函數模式和原型模式分開
     使用都存在一些問題,因此我們可以組合使用這兩種模式,通過構造函數來初始化對象的屬性,通過原型對象來實現函數
     方法的複用。這種方法很好的解決了兩種模式單獨使用時的缺點,但是有一點不足的就是,因爲使用了兩種不同的模式,
     所以對於代碼的封裝性不夠好。

 (5)第五種模式是動態原型模式,這一種模式將原型方法賦值的創建過程移動到了構造函數的內部,通過對屬性是否存在的判
     斷,可以實現僅在第一次調用函數時對原型對象賦值一次的效果。這一種方式很好地對上面的混合模式進行了封裝。

 (6)第六種模式是寄生構造函數模式,這一種模式和工廠模式的實現基本相同,我對這個模式的理解是,它主要是基於一個已
     有的類型,在實例化時對實例化的對象進行擴展。這樣既不用修改原來的構造函數,也達到了擴展對象的目的。它的一個
     缺點和工廠模式一樣,無法實現對象的識別。

 嗯我目前瞭解到的就是這麼幾種方式。

詳細資料可以參考: 《JavaScript 深入理解之對象創建》

35. JavaScript 繼承的幾種實現方式?

 我瞭解的 js 中實現繼承的幾種方式有:

 (1)第一種是以原型鏈的方式來實現繼承,但是這種實現方式存在的缺點是,在包含有引用類型的數據時,會被所有的實例
     對象所共享,容易造成修改的混亂。還有就是在創建子類型的時候不能向超類型傳遞參數。

 (2)第二種方式是使用借用構造函數的方式,這種方式是通過在子類型的函數中調用超類型的構造函數來實現的,這一種方
     法解決了不能向超類型傳遞參數的缺點,但是它存在的一個問題就是無法實現函數方法的複用,並且超類型原型定義的
     方法子類型也沒有辦法訪問到。

 (3)第三種方式是組合繼承,組合繼承是將原型鏈和借用構造函數組合起來使用的一種方式。通過借用構造函數的方式來實
     現類型的屬性的繼承,通過將子類型的原型設置爲超類型的實例來實現方法的繼承。這種方式解決了上面的兩種模式單
     獨使用時的問題,但是由於我們是以超類型的實例來作爲子類型的原型,所以調用了兩次超類的構造函數,造成了子類
     型的原型中多了很多不必要的屬性。

 (4)第四種方式是原型式繼承,原型式繼承的主要思路就是基於已有的對象來創建新的對象,實現的原理是,向函數中傳入
     一個對象,然後返回一個以這個對象爲原型的對象。這種繼承的思路主要不是爲了實現創造一種新的類型,只是對某個
     對象實現一種簡單繼承,ES5 中定義的 Object.create() 方法就是原型式繼承的實現。缺點與原型鏈方式相同。

 (5)第五種方式是寄生式繼承,寄生式繼承的思路是創建一個用於封裝繼承過程的函數,通過傳入一個對象,然後複製一個
     對象的副本,然後對象進行擴展,最後返回這個對象。這個擴展的過程就可以理解是一種繼承。這種繼承的優點就是對
     一個簡單對象實現繼承,如果這個對象不是我們的自定義類型時。缺點是沒有辦法實現函數的複用。

 (6)第六種方式是寄生式組合繼承,組合繼承的缺點就是使用超類型的實例做爲子類型的原型,導致添加了不必要的原型屬
     性。寄生式組合繼承的方式是使用超類型的原型的副本來作爲子類型的原型,這樣就避免了創建不必要的屬性。

詳細資料可以參考: 《JavaScript 深入理解之繼承》

36. 寄生式組合繼承的實現?

 function Person(name) {
   this.name = name;
 }

 Person.prototype.sayName = function () {
   console.log("My name is " + this.name + ".");
 }

 function Student(name, grade) {
   Person.call(this, name);
   this.grade = grade;
 }

 Student.prototype = Object.create(Person.prototype);
 Student.prototype.constructor = Student;

 Student.prototype.sayMyGrade = function () {
   console.log("My grade is " + this.grade + ".");
 } 

37. Javascript 的作用域鏈?

 作用域鏈的作用是保證對執行環境有權訪問的所有變量和函數的有序訪問,通過作用域鏈,我們可以訪問到外層環境的變量和
 函數。
 
 作用域鏈的本質上是一個指向變量對象的指針列表。變量對象是一個包含了執行環境中所有變量和函數的對象。作用域鏈的前
 端始終都是當前執行上下文的變量對象。全局執行上下文的變量對象(也就是全局對象)始終是作用域鏈的最後一個對象。

 當我們查找一個變量時,如果當前執行環境中沒有找到,我們可以沿着作用域鏈向後查找。

 作用域鏈的創建過程跟執行上下文的建立有關....

詳細資料可以參考: 《JavaScript 深入理解之作用域鏈》

38. 談談 This 對象的理解。

 this 是執行上下文中的一個屬性,它指向最後一次調用這個方法的對象。在實際開發中,this 的指向可以通過四種調用模
 式來判斷。

 (1)第一種是函數調用模式,當一個函數不是一個對象的屬性時,直接作爲函數來調用時,this 指向全局對象。

 (2)第二種是方法調用模式,如果一個函數作爲一個對象的方法來調用時,this 指向這個對象。

 (3)第三種是構造器調用模式,如果一個函數用 new 調用時,函數執行前會新創建一個對象,this 指向這個新創建的對
     象。
 
 (4)第四種是 apply 、 call 和 bind 調用模式,這三個方法都可以顯示的指定調用函數的 this 指向。其中 apply
     方法接收兩個參數:一個是 this 綁定的對象,一個是參數數組。call 方法接收的參數,第一個是 this 綁定的對象
     ,後面的其餘參數是傳入函數執行的參數。也就是說,在使用 call() 方法時,傳遞給函數的參數必須逐個列舉出來。b
     ind 方法通過傳入一個對象,返回一個 this 綁定了傳入對象的新函數。這個函數的 this 指向除了使用 new 時會
     被改變,其他情況下都不會改變。

 這四種方式,使用構造器調用模式的優先級最高,然後是 apply 、 call 和 bind 調用模式,然後是方法調用模式,然後
 是函數調用模式。

《JavaScript 深入理解之 this 詳解》

39. eval 是做什麼的?

 它的功能是把對應的字符串解析成 JS 代碼並運行。

 應該避免使用 eval,不安全,非常耗性能(2次,一次解析成 js 語句,一次執行)。

詳細資料可以參考: 《eval()》

40. 什麼是 DOM 和 BOM?

 DOM 指的是文檔對象模型,它指的是把文檔當做一個對象來對待,這個對象主要定義了處理網頁內容的方法和接口。

 BOM 指的是瀏覽器對象模型,它指的是把瀏覽器當做一個對象來對待,這個對象主要定義了與瀏覽器進行交互的法和接口。BOM
 的核心是 window,而 window 對象具有雙重角色,它既是通過 js 訪問瀏覽器窗口的一個接口,又是一個 Global(全局)
 對象。這意味着在網頁中定義的任何對象,變量和函數,都作爲全局對象的一個屬性或者方法存在。window 對象含有 locati
 on 對象、navigator 對象、screen 對象等子對象,並且 DOM 的最根本的對象 document 對象也是 BOM 的 window 對
 象的子對象。

詳細資料可以參考: 《DOM, DOCUMENT, BOM, WINDOW 有什麼區別?》 《Window 對象》 《DOM 與 BOM 分別是什麼,有何關聯?》 《JavaScript 學習總結(三)BOM 和 DOM 詳解》

41. 寫一個通用的事件偵聽器函數。

 const EventUtils = {

   // 視能力分別使用dom0||dom2||IE方式 來綁定事件
   // 添加事件
   addEvent: function (element, type, handler) {
     if (element.addEventListener) {
       element.addEventListener(type, handler, false);
     } else if (element.attachEvent) {
       element.attachEvent("on" + type, handler);
     } else {
       element["on" + type] = handler;
     }

   },

   // 移除事件
   removeEvent: function (element, type, handler) {
     if (element.removeEventListener) {
       element.removeEventListener(type, handler, false);
     } else if (element.detachEvent) {
       element.detachEvent("on" + type, handler);
     } else {
       element["on" + type] = null;
     }
   },

   // 獲取事件目標
   getTarget: function (event) {
     return event.target || event.srcElement;
   },

   // 獲取 event 對象的引用,取到事件的所有信息,確保隨時能使用 event
   getEvent: function (event) {
     return event || window.event;
   },

   // 阻止事件(主要是事件冒泡,因爲 IE 不支持事件捕獲)
   stopPropagation: function (event) {
     if (event.stopPropagation) {
       event.stopPropagation();
     } else {
       event.cancelBubble = true;
     }
   },

   // 取消事件的默認行爲
   preventDefault: function (event) {
     if (event.preventDefault) {
       event.preventDefault();
     } else {
       event.returnValue = false;
     }
   }
 }

詳細資料可以參考: 《JS 事件模型》

42. 事件是什麼?IE 與火狐的事件機制有什麼區別? 如何阻止冒泡?

 (1)事件是用戶操作網頁時發生的交互動作,比如 click/move, 事件除了用戶觸發的動作外,還可以是文檔加載,窗口滾動
     和大小調整。事件被封裝成一個 event 對象,包含了該事件發生時的所有相關信息( event 的屬性)以及可以對事件進
     行的操作( event 的方法)。
 
 (2)事件處理機制:IE 支持事件冒泡、Firefox 同時支持兩種事件模型,也就是:事件冒泡和事件捕獲。

 (3)event.stopPropagation() 或者 ie 下的方法 event.cancelBubble = true;

詳細資料可以參考: 《Javascript 事件模型系列(一)事件及事件的三種模型》 《Javascript 事件模型:事件捕獲和事件冒泡》

43. 三種事件模型是什麼?

 事件是用戶操作網頁時發生的交互動作或者網頁本身的一些操作,現代瀏覽器一共有三種事件模型。

 第一種事件模型是最早的 DOM0 級模型,這種模型不會傳播,所以沒有事件流的概念,但是現在有的瀏覽器支持以冒泡的方式實
 現,它可以在網頁中直接定義監聽函數,也可以通過 js 屬性來指定監聽函數。這種方式是所有瀏覽器都兼容的。

 第二種事件模型是 IE 事件模型,在該事件模型中,一次事件共有兩個過程,事件處理階段,和事件冒泡階段。事件處理階段會
 首先執行目標元素綁定的監聽事件。然後是事件冒泡階段,冒泡指的是事件從目標元素冒泡到 document,依次檢查經過的節點
 是否綁定了事件監聽函數,如果有則執行。這種模型通過 attachEvent 來添加監聽函數,可以添加多個監聽函數,會按順序依
 次執行。

 第三種是 DOM2 級事件模型,在該事件模型中,一次事件共有三個過程,第一個過程是事件捕獲階段。捕獲指的是事件從 docu
 ment 一直向下傳播到目標元素,依次檢查經過的節點是否綁定了事件監聽函數,如果有則執行。後面兩個階段和 IE 事件模型
 的兩個階段相同。這種事件模型,事件綁定的函數是 addEventListener,其中第三個參數可以指定事件是否在捕獲階段執行。

詳細資料可以參考: 《一個 DOM 元素綁定多個事件時,先執行冒泡還是捕獲》

44. 事件委託是什麼?

 事件委託本質上是利用了瀏覽器事件冒泡的機制。因爲事件在冒泡過程中會上傳到父節點,並且父節點可以通過事件對象獲取到
 目標節點,因此可以把子節點的監聽函數定義在父節點上,由父節點的監聽函數統一處理多個子元素的事件,這種方式稱爲事件
 代理。

 使用事件代理我們可以不必要爲每一個子元素都綁定一個監聽事件,這樣減少了內存上的消耗。並且使用事件代理我們還可以實
 現事件的動態綁定,比如說新增了一個子節點,我們並不需要單獨地爲它添加一個監聽事件,它所發生的事件會交給父元素中的
 監聽函數來處理。

詳細資料可以參考: 《JavaScript 事件委託詳解》

45. [“1”, “2”, “3”].map(parseInt) 答案是多少?

 parseInt() 函數能解析一個字符串,並返回一個整數,需要兩個參數 (val, radix),其中 radix 表示要解析的數字的基
 數。(該值介於 2 ~ 36 之間,並且字符串中的數字不能大於 radix 才能正確返回數字結果值)。


 此處 map 傳了 3 個參數 (element, index, array),默認第三個參數被忽略掉,因此三次傳入的參數分別爲

 "1-0", "2-1", "3-2"

 因爲字符串的值不能大於基數,因此後面兩次調用均失敗,返回 NaN ,第一次基數爲 0 ,按十進制解析返回 1。

詳細資料可以參考: [《爲什麼 “1”, “2”, “3”].map(parseInt) 返回 [1,NaN,NaN]?》

46. 什麼是閉包,爲什麼要用它?

 閉包是指有權訪問另一個函數作用域中變量的函數,創建閉包的最常見的方式就是在一個函數內創建另一個函數,創建的函數可以
 訪問到當前函數的局部變量。

 閉包有兩個常用的用途。

 閉包的第一個用途是使我們在函數外部能夠訪問到函數內部的變量。通過使用閉包,我們可以通過在外部調用閉包函數,從而在外
 部訪問到函數內部的變量,可以使用這種方法來創建私有變量。

 函數的另一個用途是使已經運行結束的函數上下文中的變量對象繼續留在內存中,因爲閉包函數保留了這個變量對象的引用,所以
 這個變量對象不會被回收。

 其實閉包的本質就是作用域鏈的一個特殊的應用,只要瞭解了作用域鏈的創建過程,就能夠理解閉包的實現原理。

詳細資料可以參考: 《JavaScript 深入理解之閉包》

47. javascript 代碼中的 “use strict”; 是什麼意思 ? 使用它區別是什麼?

相關知識點:

 use strict 是一種 ECMAscript5 添加的(嚴格)運行模式,這種模式使得 Javascript 在更嚴格的條件下運行。
 
 設立"嚴格模式"的目的,主要有以下幾個:

     - 消除 Javascript 語法的一些不合理、不嚴謹之處,減少一些怪異行爲;

     - 消除代碼運行的一些不安全之處,保證代碼運行的安全;

     - 提高編譯器效率,增加運行速度;

     - 爲未來新版本的 Javascript 做好鋪墊。

 區別:

 (1)禁止使用 with 語句。
 (2)禁止 this 關鍵字指向全局對象。
 (3)對象不能有重名的屬性。

  ......

回答:

 use strict 指的是嚴格運行模式,在這種模式對 js 的使用添加了一些限制。比如說禁止 this 指向全局對象,還有禁止使
 用 with 語句等。設立嚴格模式的目的,主要是爲了消除代碼使用中的一些不安全的使用方式,也是爲了消除 js 語法本身的一
 些不合理的地方,以此來減少一些運行時的怪異的行爲。同時使用嚴格運行模式也能夠提高編譯的效率,從而提高代碼的運行速度。
 我認爲嚴格模式代表了 js 一種更合理、更安全、更嚴謹的發展方向。

詳細資料可以參考: 《Javascript 嚴格模式詳解》

48. 如何判斷一個對象是否屬於某個類?

 第一種方式是使用 instanceof 運算符來判斷構造函數的 prototype 屬性是否出現在對象的原型鏈中的任何位置。

 第二種方式可以通過對象的 constructor 屬性來判斷,對象的 constructor 屬性指向該對象的構造函數,但是這種方式不
 是很安全,因爲 constructor 屬性可以被改寫。

 第三種方式,如果需要判斷的是某個內置的引用類型的話,可以使用 Object.prototype.toString() 方法來打印對象的 
 [[Class]] 屬性來進行判斷。

詳細資料可以參考: 《js 判斷一個對象是否屬於某一類》

49. instanceof 的作用?

 instanceof 運算符用於判斷構造函數的 prototype 屬性是否出現在對象的原型鏈中的任何位置。

 實現:

 function myInstanceof(left, right) {
   let proto = Object.getPrototypeOf(left), // 獲取對象的原型
     prototype = right.prototype; // 獲取構造函數的 prototype 對象

   // 判斷構造函數的 prototype 對象是否在對象的原型鏈上
   while (true) {
     if (!proto) return false;
     if (proto === prototype) return true;

     proto = Object.getPrototypeOf(proto);
   }
 }

詳細資料可以參考: 《instanceof》

50. new 操作符具體幹了什麼呢?如何實現?

 (1)首先創建了一個新的空對象
 (2)設置原型,將對象的原型設置爲函數的 prototype 對象。
 (3)讓函數的 this 指向這個對象,執行構造函數的代碼(爲這個新對象添加屬性)
 (4)判斷函數的返回值類型,如果是值類型,返回創建的對象。如果是引用類型,就返回這個引用類型的對象。
 
 實現:

 function objectFactory() {

   let newObject = null,
     constructor = Array.prototype.shift.call(arguments),
     result = null;
   
   // 參數判斷
   if (typeof constructor !== "function") {
     console.error("type error");
     return;
   };

   // 新建一個空對象,對象的原型爲構造函數的 prototype 對象
   newObject = Object.create(constructor.prototype);

   // 將 this 指向新建對象,並執行函數
   result = constructor.apply(newObject, arguments);
   
   // 判斷返回對象
   let flag = result && (typeof result === "object" || typeof result === "function");

   // 判斷返回結果
   return flag ? result : newObject;
 }

 // 使用方法
 objectFactory(構造函數,初始化參數)

詳細資料可以參考: 《new 操作符具體幹了什麼?》 《JavaScript 深入之 new 的模擬實現》

51. Javascript中,有一個函數,執行時對象查找時,永遠不會去查找原型,這個函數是?

 hasOwnProperty

 所有繼承了 Object 的對象都會繼承到 hasOwnProperty 方法。這個方法可以用來檢測一個對象是否含有特定的自身屬性,和
 in 運算符不同,該方法會忽略掉那些從原型鏈上繼承到的屬性。

詳細資料可以參考: 《Object.prototype.hasOwnProperty()》

52. 對於 JSON 的瞭解?

相關知識點:

 JSON 是一種數據交換格式,基於文本,優於輕量,用於交換數據。

 JSON 可以表示數字、布爾值、字符串、null、數組(值的有序序列),以及由這些值(或數組、對象)所組成的對象(字符串與
 值的映射)。

 JSON 使用 JavaScript 語法,但是 JSON 格式僅僅是一個文本。文本可以被任何編程語言讀取及作爲數據格式傳遞。

回答:

 JSON 是一種基於文本的輕量級的數據交換格式。它可以被任何的編程語言讀取和作爲數據格式來傳遞。

 在項目開發中,我們使用 JSON 作爲前後端數據交換的方式。在前端我們通過將一個符合 JSON 格式的數據結構序列化爲 JSON
 字符串,然後將它傳遞到後端,後端通過 JSON 格式的字符串解析後生成對應的數據結構,以此來實現前後端數據的一個傳遞。
 
 因爲 JSON 的語法是基於 js 的,因此很容易將 JSON 和 js 中的對象弄混,但是我們應該注意的是 JSON 和 js 中的對象
 不是一回事,JSON 中對象格式更加嚴格,比如說在 JSON 中屬性值不能爲函數,不能出現 NaN 這樣的屬性值等,因此大多數的
 js 對象是不符合 JSON 對象的格式的。

 在 js 中提供了兩個函數來實現 js 數據結構和 JSON 格式的轉換處理,一個是 JSON.stringify 函數,通過傳入一個符合
 JSON 格式的數據結構,將其轉換爲一個 JSON 字符串。如果傳入的數據結構不符合 JSON 格式,那麼在序列化的時候會對這些
 值進行對應的特殊處理,使其符合規範。在前端向後端發送數據時,我們可以調用這個函數將數據對象轉化爲 JSON 格式的字符串。

 另一個函數 JSON.parse() 函數,這個函數用來將 JSON 格式的字符串轉換爲一個 js 數據結構,如果傳入的字符串不是標準
 的 JSON 格式的字符串的話,將會拋出錯誤。當我們從後端接收到 JSON 格式的字符串時,我們可以通過這個方法來將其解析爲
 一個 js 數據結構,以此來進行數據的訪問。

詳細資料可以參考: 《深入瞭解 JavaScript 中的 JSON 》

53. [].forEach.call($$(""),function(a){a.style.outline=“1px solid #”+(~~(Math.random()(1<<24))).toString(16)}) 能解釋一下這段代碼的意思嗎?

 (1)選取頁面所有 DOM 元素。在瀏覽器的控制檯中可以使用$$()方法來獲取頁面中相應的元素,這是現代瀏覽器提供的一個命
     令行 API 相當於 document.querySelectorAll 方法。

 (2)循環遍歷 DOM 元素

 (3)給元素添加 outline 。由於渲染的 outline 是不在 CSS 盒模型中的,所以爲元素添加 outline 並不會影響元素的
     大小和頁面的佈局。

 (4)生成隨機顏色函數。Math.random()*(1<<24) 可以得到 0~2^24 - 1 之間的隨機數,因爲得到的是一個浮點數,但我
     們只需要整數部分,使用取反操作符 ~ 連續兩次取反獲得整數部分,然後再用 toString(16) 的方式,轉換爲一個十六
     進制的字符串。

詳細資料可以參考: 《通過一行代碼學 JavaScript》

54. js 延遲加載的方式有哪些?

相關知識點:

 js 延遲加載,也就是等頁面加載完成之後再加載 JavaScript 文件。 js 延遲加載有助於提高頁面加載速度。

 一般有以下幾種方式:

     defer 屬性
     async 屬性
     動態創建 DOM 方式
     使用 setTimeout 延遲方法
     讓 JS 最後加載

回答:

 js 的加載、解析和執行會阻塞頁面的渲染過程,因此我們希望 js 腳本能夠儘可能的延遲加載,提高頁面的渲染速度。

 我瞭解到的幾種方式是

 第一種方式是我們一般採用的是將 js 腳本放在文檔的底部,來使 js 腳本儘可能的在最後來加載執行。

 第二種方式是給 js 腳本添加 defer 屬性,這個屬性會讓腳本的加載與文檔的解析同步解析,然後在文檔解析完成後再執行這個
 腳本文件,這樣的話就能使頁面的渲染不被阻塞。多個設置了 defer 屬性的腳本按規範來說最後是順序執行的,但是在一些瀏覽
 器中可能不是這樣。

 第三種方式是給 js 腳本添加 async 屬性,這個屬性會使腳本異步加載,不會阻塞頁面的解析過程,但是當腳本加載完成後立即
 執行 js 腳本,這個時候如果文檔沒有解析完成的話同樣會阻塞。多個 async 屬性的腳本的執行順序是不可預測的,一般不會按
 照代碼的順序依次執行。

 第四種方式是動態創建 DOM 標籤的方式,我們可以對文檔的加載事件進行監聽,當文檔加載完成後再動態的創建 script 標籤來
 引入 js 腳本。

詳細資料可以參考: 《JS 延遲加載的幾種方式》 《HTML 5 async 屬性》

55. Ajax 是什麼? 如何創建一個Ajax?

相關知識點:

 2005年2月,AJAX 這個詞第一次正式提出,它是 Asynchronous JavaScript and XML 的縮寫,指的是通過 JavaScript 的
 異步通信,從服務器獲取 XML 文檔從中提取數據,再更新當前網頁的對應部分,而不用刷新整個網頁。

 具體來說,AJAX 包括以下幾個步驟。

 (1)創建 XMLHttpRequest 對象,也就是創建一個異步調用對象
 (2)創建一個新的 HTTP 請求,並指定該 HTTP 請求的方法、URL 及驗證信息
 (3)設置響應 HTTP 請求狀態變化的函數
 (4)發送 HTTP 請求
 (5)獲取異步調用返回的數據
 (6)使用 JavaScript 和 DOM 實現局部刷新

 一般實現:

 const SERVER_URL = "/server"

 let xhr = new XMLHttpRequest();

 // 創建 Http 請求
 xhr.open("GET", SERVER_URL, true);

 // 設置狀態監聽函數
 xhr.onreadystatechange = function () {
   if (this.readyState !== 4) return;

   // 當請求成功時
   if (this.status === 200) {
     handle(this.response);
   } else {
     console.error(this.statusText);
   }
 }

 // 設置請求失敗時的監聽函數
 xhr.onerror = function () {
   console.error(this.statusText);
 }

 // 設置請求頭信息
 xhr.responseType = "json";
 xhr.setRequestHeader("Accept", "application/json");

 // 發送 Http 請求
 xhr.send(null);


 promise 封裝實現:

 function getJSON(url) {

   // 創建一個 promise 對象
   let promise = new Promise(function (resolve, reject) {

     let xhr = new XMLHttpRequest();

     // 新建一個 http 請求
     xhr.open("GET", url, true);

     // 設置狀態的監聽函數
     xhr.onreadystatechange = function () {

       if (this.readyState !== 4) return;

       // 當請求成功或失敗時,改變 promise 的狀態
       if (this.status === 200) {
         resolve(this.response);
       } else {
         reject(new Error(this.statusText));
       }
     }

     // 設置錯誤監聽函數
     xhr.onerror = function () {
       reject(new Error(this.statusText));
     }
     
     // 設置響應的數據類型
     xhr.responseType = "json";

     // 設置請求頭信息
     xhr.setRequestHeader("Accept", "application/json");

     // 發送 http 請求
     xhr.send(null);

   })

   return promise;
 }

回答:

 我對 ajax 的理解是,它是一種異步通信的方法,通過直接由 js 腳本向服務器發起 http 通信,然後根據服務器返回的數據,
 更新網頁的相應部分,而不用刷新整個頁面的一種方法。

 創建一個 ajax 有這樣幾個步驟

 首先是創建一個 XMLHttpRequest 對象。
 
 然後在這個對象上使用 open 方法創建一個 http 請求,open 方法所需要的參數是請求的方法、請求的地址、是否異步和用戶
 的認證信息。
 
 在發起請求前,我們可以爲這個對象添加一些信息和監聽函數。比如說我們可以通過 setRequestHeader 方法來爲請求添加頭信
 息。我們還可以爲這個對象添加一個狀態監聽函數。一個 XMLHttpRequest 對象一共有 5 個狀態,當它的狀態變化時會觸發on
 readystatechange 事件,我們可以通過設置監聽函數,來處理請求成功後的結果。當對象的 readyState 變爲 4 的時候,代
 表服務器返回的數據接收完成,這個時候我們可以通過判斷請求的狀態,如果狀態是 2xx 或者 304 的話則代表返回正常。這個時
 候我們就可以通過 response 中的數據來對頁面進行更新了。

 當對象的屬性和監聽函數設置完成後,最後我們調用 sent 方法來向服務器發起請求,可以傳入參數作爲發送的數據體。

詳細資料可以參考: 《XMLHttpRequest 對象》 《從 ajax 到 fetch、axios》 《Fetch 入門》 《傳統 Ajax 已死,Fetch 永生》

56. 談一談瀏覽器的緩存機制?

 瀏覽器的緩存機制指的是通過在一段時間內保留已接收到的 web 資源的一個副本,如果在資源的有效時間內,發起了對這個資源的
 再一次請求,那麼瀏覽器會直接使用緩存的副本,而不是向服務器發起請求。使用 web 緩存可以有效地提高頁面的打開速度,減少
 不必要的網絡帶寬的消耗。

 web 資源的緩存策略一般由服務器來指定,可以分爲兩種,分別是強緩存策略和協商緩存策略。

 使用強緩存策略時,如果緩存資源有效,則直接使用緩存資源,不必再向服務器發起請求。強緩存策略可以通過兩種方式來設置,分
 別是 http 頭信息中的 Expires 屬性和 Cache-Control 屬性。

 服務器通過在響應頭中添加 Expires 屬性,來指定資源的過期時間。在過期時間以內,該資源可以被緩存使用,不必再向服務器發
 送請求。這個時間是一個絕對時間,它是服務器的時間,因此可能存在這樣的問題,就是客戶端的時間和服務器端的時間不一致,或
 者用戶可以對客戶端時間進行修改的情況,這樣就可能會影響緩存命中的結果。

 Expires 是 http1.0 中的方式,因爲它的一些缺點,在 http 1.1 中提出了一個新的頭部屬性就是 Cache-Control 屬性,
 它提供了對資源的緩存的更精確的控制。它有很多不同的值,常用的比如我們可以通過設置 max-age 來指定資源能夠被緩存的時間
 的大小,這是一個相對的時間,它會根據這個時間的大小和資源第一次請求時的時間來計算出資源過期的時間,因此相對於 Expires
 來說,這種方式更加有效一些。常用的還有比如 private ,用來規定資源只能被客戶端緩存,不能夠代理服務器所緩存。還有如 n
 o-store ,用來指定資源不能夠被緩存,no-cache 代表該資源能夠被緩存,但是立即失效,每次都需要向服務器發起請求。

 一般來說只需要設置其中一種方式就可以實現強緩存策略,當兩種方式一起使用時,Cache-Control 的優先級要高於 Expires 。

 使用協商緩存策略時,會先向服務器發送一個請求,如果資源沒有發生修改,則返回一個 304 狀態,讓瀏覽器使用本地的緩存副本。
 如果資源發生了修改,則返回修改後的資源。協商緩存也可以通過兩種方式來設置,分別是 http 頭信息中的 Etag 和 Last-Mod
 ified 屬性。

 服務器通過在響應頭中添加 Last-Modified 屬性來指出資源最後一次修改的時間,當瀏覽器下一次發起請求時,會在請求頭中添
 加一個 If-Modified-Since 的屬性,屬性值爲上一次資源返回時的 Last-Modified 的值。當請求發送到服務器後服務器會通
 過這個屬性來和資源的最後一次的修改時間來進行比較,以此來判斷資源是否做了修改。如果資源沒有修改,那麼返回 304 狀態,讓
 客戶端使用本地的緩存。如果資源已經被修改了,則返回修改後的資源。使用這種方法有一個缺點,就是 Last-Modified 標註的最
 後修改時間只能精確到秒級,如果某些文件在1秒鐘以內,被修改多次的話,那麼文件已將改變了但是 Last-Modified 卻沒有改變,
 這樣會造成緩存命中的不準確。

 因爲 Last-Modified 的這種可能發生的不準確性,http 中提供了另外一種方式,那就是 Etag 屬性。服務器在返回資源的時候,
 在頭信息中添加了 Etag 屬性,這個屬性是資源生成的唯一標識符,當資源發生改變的時候,這個值也會發生改變。在下一次資源請
 求時,瀏覽器會在請求頭中添加一個 If-None-Match 屬性,這個屬性的值就是上次返回的資源的 Etag 的值。服務接收到請求後
 會根據這個值來和資源當前的 Etag 的值來進行比較,以此來判斷資源是否發生改變,是否需要返回資源。通過這種方式,比 Last
 -Modified 的方式更加精確。

 當 Last-Modified 和 Etag 屬性同時出現的時候,Etag 的優先級更高。使用協商緩存的時候,服務器需要考慮負載平衡的問題,
 因此多個服務器上資源的 Last-Modified 應該保持一致,因爲每個服務器上 Etag 的值都不一樣,因此在考慮負載平衡時,最好
 不要設置 Etag 屬性。

 強緩存策略和協商緩存策略在緩存命中時都會直接使用本地的緩存副本,區別只在於協商緩存會向服務器發送一次請求。它們緩存不命
 中時,都會向服務器發送請求來獲取資源。在實際的緩存機制中,強緩存策略和協商緩存策略是一起合作使用的。瀏覽器首先會根據請
 求的信息判斷,強緩存是否命中,如果命中則直接使用資源。如果不命中則根據頭信息向服務器發起請求,使用協商緩存,如果協商緩
 存命中的話,則服務器不返回資源,瀏覽器直接使用本地資源的副本,如果協商緩存不命中,則瀏覽器返回最新的資源給瀏覽器。

詳細資料可以參考: 《淺談瀏覽器緩存》 《前端優化:瀏覽器緩存技術介紹》 《請求頭中的 Cache-Control》 《Cache-Control 字段值詳解》

57. Ajax 解決瀏覽器緩存問題?

 (1)在 ajax 發送請求前加上 anyAjaxObj.setRequestHeader("If-Modified-Since","0")。 

 (2)在 ajax 發送請求前加上 anyAjaxObj.setRequestHeader("Cache-Control","no-cache")。 

 (3)在 URL 後面加上一個隨機數: "fresh=" + Math.random();。 

 (4)在 URL 後面加上時間戳:"nowtime=" + new Date().getTime();。 

 (5)如果是使用 jQuery,直接這樣就可以了$.ajaxSetup({cache:false})。這樣頁面的所有 ajax 都會執行這條語句就是不需
     要保存緩存記錄。

詳細資料可以參考: 《Ajax 中瀏覽器的緩存問題解決方法》 《淺談瀏覽器緩存》

58. 同步和異步的區別?

相關知識點:

 同步,可以理解爲在執行完一個函數或方法之後,一直等待系統返回值或消息,這時程序是處於阻塞的,只有接收到返回的值或消息後
 才往下執行其他的命令。  

 異步,執行完函數或方法後,不必阻塞性地等待返回值或消息,只需要向系統委託一個異步過程,那麼當系統接收到返回值或消息時,
 系統會自動觸發委託的異步過程,從而完成一個完整的流程。 

回答:

 同步指的是當一個進程在執行某個請求的時候,如果這個請求需要等待一段時間才能返回,那麼這個進程會一直等待下去,直到消息返
 回爲止再繼續向下執行。

 異步指的是當一個進程在執行某個請求的時候,如果這個請求需要等待一段時間才能返回,這個時候進程會繼續往下執行,不會阻塞等
 待消息的返回,當消息返回時系統再通知進程進行處理。

詳細資料可以參考: 《同步和異步的區別》

59. 什麼是瀏覽器的同源政策?

 我對瀏覽器的同源政策的理解是,一個域下的 js 腳本在未經允許的情況下,不能夠訪問另一個域的內容。這裏的同源的指的是兩個
 域的協議、域名、端口號必須相同,否則則不屬於同一個域。

 同源政策主要限制了三個方面

 第一個是當前域下的 js 腳本不能夠訪問其他域下的 cookie、localStorage 和 indexDB。

 第二個是當前域下的 js 腳本不能夠操作訪問操作其他域下的 DOM。

 第三個是當前域下 ajax 無法發送跨域請求。

 同源政策的目的主要是爲了保證用戶的信息安全,它只是對 js 腳本的一種限制,並不是對瀏覽器的限制,對於一般的 img、或者
 script 腳本請求都不會有跨域的限制,這是因爲這些操作都不會通過響應結果來進行可能出現安全問題的操作。

60. 如何解決跨域問題?

相關知識點:

 (1) 通過 jsonp 跨域
 (2) document.domain + iframe 跨域
 (3) location.hash + iframe
 (4) window.name + iframe 跨域
 (5) postMessage 跨域
 (6) 跨域資源共享(CORS)
 (7) nginx 代理跨域
 (8) nodejs 中間件代理跨域
 (9) WebSocket 協議跨域

回答:

 解決跨域的方法我們可以根據我們想要實現的目的來劃分。

 首先我們如果只是想要實現主域名下的不同子域名的跨域操作,我們可以使用設置 document.domain 來解決。

 (1)將 document.domain 設置爲主域名,來實現相同子域名的跨域操作,這個時候主域名下的 cookie 就能夠被子域名所訪問。
     同時如果文檔中含有主域名相同,子域名不同的 iframe 的話,我們也可以對這個 iframe 進行操作。

 如果是想要解決不同跨域窗口間的通信問題,比如說一個頁面想要和頁面的中的不同源的 iframe 進行通信的問題,我們可以使用 
 location.hash 或者 window.name 或者 postMessage 來解決。

 (2)使用 location.hash 的方法,我們可以在主頁面動態的修改 iframe 窗口的 hash 值,然後在 iframe 窗口裏實現監聽
     函數來實現這樣一個單向的通信。因爲在 iframe 是沒有辦法訪問到不同源的父級窗口的,所以我們不能直接修改父級窗口的 
     hash 值來實現通信,我們可以在 iframe 中再加入一個 iframe ,這個 iframe 的內容是和父級頁面同源的,所以我們可
     以 window.parent.parent 來修改最頂級頁面的 src,以此來實現雙向通信。

 (3)使用 window.name 的方法,主要是基於同一個窗口中設置了 window.name 後不同源的頁面也可以訪問,所以不同源的子頁
     面可以首先在 window.name 中寫入數據,然後跳轉到一個和父級同源的頁面。這個時候級頁面就可以訪問同源的子頁面中 wi
     ndow.name 中的數據了,這種方式的好處是可以傳輸的數據量大。

 (4)使用 postMessage 來解決的方法,這是一個 h5 中新增的一個 api。通過它我們可以實現多窗口間的信息傳遞,通過獲取到
     指定窗口的引用,然後調用 postMessage 來發送信息,在窗口中我們通過對 message 信息的監聽來接收信息,以此來實現不
     同源間的信息交換。

 如果是像解決 ajax 無法提交跨域請求的問題,我們可以使用 jsonp、cors、websocket 協議、服務器代理來解決問題。
     
 (5)使用 jsonp 來實現跨域請求,它的主要原理是通過動態構建 script  標籤來實現跨域請求,因爲瀏覽器對 script 標籤的
     引入沒有跨域的訪問限制 。通過在請求的 url 後指定一個回調函數,然後服務器在返回數據的時候,構建一個 json 數據的
     包裝,這個包裝就是回調函數,然後返回給前端,前端接收到數據後,因爲請求的是腳本文件,所以會直接執行,這樣我們先前
     定義好的回調函數就可以被調用,從而實現了跨域請求的處理。這種方式只能用於 get 請求。

 (6)使用 CORS 的方式,CORS 是一個 W3C 標準,全稱是"跨域資源共享"。CORS 需要瀏覽器和服務器同時支持。目前,所有瀏覽
     器都支持該功能,因此我們只需要在服務器端配置就行。瀏覽器將 CORS 請求分成兩類:簡單請求和非簡單請求。對於簡單請求
     ,瀏覽器直接發出 CORS 請求。具體來說,就是會在頭信息之中,增加一個 Origin 字段。Origin 字段用來說明本次請求來
     自哪個源。服務器根據這個值,決定是否同意這次請求。對於如果 Origin 指定的源,不在許可範圍內,服務器會返回一個正常
     的 HTTP 迴應。瀏覽器發現,這個迴應的頭信息沒有包含 Access-Control-Allow-Origin 字段,就知道出錯了,從而拋
     出一個錯誤,ajax 不會收到響應信息。如果成功的話會包含一些以 Access-Control- 開頭的字段。

     非簡單請求,瀏覽器會先發出一次預檢請求,來判斷該域名是否在服務器的白名單中,如果收到肯定回覆後纔會發起請求。

 (7)使用 websocket 協議,這個協議沒有同源限制。

 (8)使用服務器來代理跨域的訪問請求,就是有跨域的請求操作時發送請求給後端,讓後端代爲請求,然後最後將獲取的結果發返
     回。

詳細資料可以參考: 《前端常見跨域解決方案(全)》 《瀏覽器同源政策及其規避方法》 《跨域,你需要知道的全在這裏》 《爲什麼 form 表單提交沒有跨域問題,但 ajax 提交有跨域問題?》

61. 服務器代理轉發時,該如何處理 cookie?

詳細資料可以參考: 《深入淺出 Nginx》

62. 簡單談一下 cookie ?

 我的理解是 cookie 是服務器提供的一種用於維護會話狀態信息的數據,通過服務器發送到瀏覽器,瀏覽器保存在本地,當下一次
 有同源的請求時,將保存的 cookie 值添加到請求頭部,發送給服務端。這可以用來實現記錄用戶登錄狀態等功能。cookie 一般
 可以存儲 4k 大小的數據,並且只能夠被同源的網頁所共享訪問。

 服務器端可以使用 Set-Cookie 的響應頭部來配置 cookie 信息。一條 cookie 包括了5個屬性值 expires、domain、path、
 secure、HttpOnly。其中 expires 指定了 cookie 失效的時間,domain 是域名、path是路徑,domain 和 path 一起限
 制了 cookie 能夠被哪些 url 訪問。secure 規定了 cookie 只能在確保安全的情況下傳輸,HttpOnly 規定了這個 cookie
 只能被服務器訪問,不能使用 js 腳本訪問。

 在發生 xhr 的跨域請求的時候,即使是同源下的 cookie,也不會被自動添加到請求頭部,除非顯示地規定。

詳細資料可以參考: 《HTTP cookies》 《聊一聊 cookie》

63. 模塊化開發怎麼做?

 我對模塊的理解是,一個模塊是實現一個特定功能的一組方法。在最開始的時候,js 只實現一些簡單的功能,所以並沒有模塊的概念
 ,但隨着程序越來越複雜,代碼的模塊化開發變得越來越重要。

 由於函數具有獨立作用域的特點,最原始的寫法是使用函數來作爲模塊,幾個函數作爲一個模塊,但是這種方式容易造成全局變量的污
 染,並且模塊間沒有聯繫。

 後面提出了對象寫法,通過將函數作爲一個對象的方法來實現,這樣解決了直接使用函數作爲模塊的一些缺點,但是這種辦法會暴露所
 有的所有的模塊成員,外部代碼可以修改內部屬性的值。

 現在最常用的是立即執行函數的寫法,通過利用閉包來實現模塊私有作用域的建立,同時不會對全局作用域造成污染。

詳細資料可以參考: 《淺談模塊化開發》 《Javascript 模塊化編程(一):模塊的寫法》 《前端模塊化:CommonJS,AMD,CMD,ES6》 《Module 的語法》

64. js 的幾種模塊規範?

 js 中現在比較成熟的有四種模塊加載方案。
 
 第一種是 CommonJS 方案,它通過 require 來引入模塊,通過 module.exports 定義模塊的輸出接口。這種模塊加載方案是
 服務器端的解決方案,它是以同步的方式來引入模塊的,因爲在服務端文件都存儲在本地磁盤,所以讀取非常快,所以以同步的方式
 加載沒有問題。但如果是在瀏覽器端,由於模塊的加載是使用網絡請求,因此使用異步加載的方式更加合適。

 第二種是 AMD 方案,這種方案採用異步加載的方式來加載模塊,模塊的加載不影響後面語句的執行,所有依賴這個模塊的語句都定
 義在一個回調函數裏,等到加載完成後再執行回調函數。require.js 實現了 AMD 規範。

 第三種是 CMD 方案,這種方案和 AMD 方案都是爲了解決異步模塊加載的問題,sea.js 實現了 CMD 規範。它和 require.js
 的區別在於模塊定義時對依賴的處理不同和對依賴模塊的執行時機的處理不同。參考60

 第四種方案是 ES6 提出的方案,使用 import 和 export 的形式來導入導出模塊。這種方案和上面三種方案都不同。參考 61。

65. AMD 和 CMD 規範的區別?

 它們之間的主要區別有兩個方面。

 (1)第一個方面是在模塊定義時對依賴的處理不同。AMD 推崇依賴前置,在定義模塊的時候就要聲明其依賴的模塊。而 CMD 推崇
     就近依賴,只有在用到某個模塊的時候再去 require。

 (2)第二個方面是對依賴模塊的執行時機處理不同。首先 AMD 和 CMD 對於模塊的加載方式都是異步加載,不過它們的區別在於
     模塊的執行時機,AMD 在依賴模塊加載完成後就直接執行依賴模塊,依賴模塊的執行順序和我們書寫的順序不一定一致。而 CMD
     在依賴模塊加載完成後並不執行,只是下載而已,等到所有的依賴模塊都加載好後,進入回調函數邏輯,遇到 require 語句
     的時候才執行對應的模塊,這樣模塊的執行順序就和我們書寫的順序保持一致了。

 // CMD
 define(function(require, exports, module) {
  var a = require('./a')
  a.doSomething()
  // 此處略去 100 行
  var b = require('./b') // 依賴可以就近書寫
  b.doSomething()
  // ...
 })

 // AMD 默認推薦
 define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好
  a.doSomething()
  // 此處略去 100 行
  b.doSomething()
  // ...
 })

詳細資料可以參考: 《前端模塊化,AMD 與 CMD 的區別》

66. ES6 模塊與 CommonJS 模塊、AMD、CMD 的差異。

 (1)CommonJS 模塊輸出的是一個值的拷貝,ES6 模塊輸出的是值的引用。CommonJS 模塊輸出的是值的拷貝,也就是說,一
     旦輸出一個值,模塊內部的變化就影響不到這個值。ES6 模塊的運行機制與 CommonJS 不一樣。JS 引擎對腳本靜態分析
     的時候,遇到模塊加載命令 import,就會生成一個只讀引用。等到腳本真正執行時,再根據這個只讀引用,到被加載的那
     個模塊裏面去取值。

 (2)CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口。CommonJS 模塊就是對象,即在輸入時是先加載整個模塊,
     生成一個對象,然後再從這個對象上面讀取方法,這種加載稱爲“運行時加載”。而 ES6 模塊不是對象,它的對外接口只是
     一種靜態定義,在代碼靜態解析階段就會生成。

67. requireJS 的核心原理是什麼?(如何動態加載的?如何避免多次加載的?如何 緩存的?)

 require.js 的核心原理是通過動態創建 script 腳本來異步引入模塊,然後對每個腳本的 load 事件進行監聽,如果每個腳
 本都加載完成了,再調用回調函數。

詳細資料可以參考: 《requireJS 的用法和原理分析》 《requireJS 的核心原理是什麼?》 《從 RequireJs 源碼剖析腳本加載原理》 《requireJS 原理分析》

68. JS 模塊加載器的輪子怎麼造,也就是如何實現一個模塊加載器?

詳細資料可以參考: 《JS 模塊加載器加載原理是怎麼樣的?》

69. ECMAScript6 怎麼寫 class,爲什麼會出現 class 這種東西?

 在我看來 ES6 新添加的 class 只是爲了補充 js 中缺少的一些面嚮對象語言的特性,但本質上來說它只是一種語法糖,不是
 一個新的東西,其背後還是原型繼承的思想。通過加入 class 可以有利於我們更好的組織代碼。

 在 class 中添加的方法,其實是添加在類的原型上的。

詳細資料可以參考: 《ECMAScript 6 實現了 class,對 JavaScript 前端開發有什麼意義?》 《Class 的基本語法》

70. documen.write 和 innerHTML 的區別?

 document.write 的內容會代替整個文檔內容,會重寫整個頁面。

 innerHTML 的內容只是替代指定元素的內容,只會重寫頁面中的部分內容。

詳細資料可以參考: 《簡述 document.write 和 innerHTML 的區別。》

71. DOM 操作——怎樣添加、移除、移動、複製、創建和查找節點?

 (1)創建新節點
     createDocumentFragment(node)    
     createElement(node)   
     createTextNode(text)   

 (2)添加、移除、替換、插入
     appendChild(node)
     removeChild(node)
     replaceChild(new,old)
     insertBefore(new,old)

 (3)查找
     getElementById()  
     getElementsByName()  
     getElementsByTagName()
     getElementsByClassName()
     querySelector()
     querySelectorAll() 

 (4)屬性操作
     getAttribute(key)
     setAttribute(key,value)
     hasAttribute(key)
     removeAttribute(key)  
       
       

詳細資料可以參考: 《DOM 概述》 《原生 JavaScript 的 DOM 操作彙總》 《原生 JS 中 DOM 節點相關 API 合集》

72. innerHTML 與 outerHTML 的區別?

 對於這樣一個 HTML 元素:<div>content<br/></div>。

 innerHTML:內部 HTML,content<br/>;
 outerHTML:外部 HTML,<div>content<br/></div>;
 innerText:內部文本,content ;
 outerText:內部文本,content ;

73. .call() 和 .apply() 的區別?

 它們的作用一模一樣,區別僅在於傳入參數的形式的不同。

 apply 接受兩個參數,第一個參數指定了函數體內 this 對象的指向,第二個參數爲一個帶下標的集合,這個集合可以爲數組,
 也可以爲類數組,apply 方法把這個集合中的元素作爲參數傳遞給被調用的函數。

 call 傳入的參數數量不固定,跟 apply 相同的是,第一個參數也是代表函數體內的 this 指向,從第二個參數開始往後,每
 個參數被依次傳入函數。

詳細資料可以參考: 《apply、call 的區別和用途》

74. JavaScript 類數組對象的定義?

 一個擁有 length 屬性和若干索引屬性的對象就可以被稱爲類數組對象,類數組對象和數組類似,但是不能調用數組的方法。

 常見的類數組對象有 arguments 和 DOM 方法的返回結果,還有一個函數也可以被看作是類數組對象,因爲它含有 length 
 屬性值,代表可接收的參數個數。

 常見的類數組轉換爲數組的方法有這樣幾種:

 (1)通過 call 調用數組的 slice 方法來實現轉換
     
     Array.prototype.slice.call(arrayLike);

 (2)通過 call 調用數組的 splice 方法來實現轉換

     Array.prototype.splice.call(arrayLike, 0); 

 (3)通過 apply 調用數組的 concat 方法來實現轉換

    Array.prototype.concat.apply([], arrayLike)
 
 (4)通過 Array.from 方法來實現轉換

    Array.from(arrayLike);

詳細的資料可以參考: 《JavaScript 深入之類數組對象與 arguments》 《javascript 類數組》 《深入理解 JavaScript 類數組》

75. 數組和對象有哪些原生方法,列舉一下?

 數組和字符串的轉換方法:toString()、toLocalString()、join() 其中 join() 方法可以指定轉換爲字符串時的分
 隔符。

 數組尾部操作的方法 pop()push(),push 方法可以傳入多個參數。

 數組首部操作的方法 shift()unshift()

 重排序的方法 reverse()sort(),sort() 方法可以傳入一個函數來進行比較,傳入前後兩個值,如果返回值爲正數,
 則交換兩個參數的位置。

 數組連接的方法 concat() ,返回的是拼接好的數組,不影響原數組。

 數組截取辦法 slice(),用於截取數組中的一部分返回,不影響原數組。

 數組插入方法 

計算機網絡知識總結

本部分主要是筆者在複習計算機網絡相關知識和一些相關面試題時所做的筆記,如果出現錯誤,希望大家指出!

目錄

應用層

應用層協議定義了應用進程間的交互和通信規則,不同主機的應用進程間如何相互傳遞報文,比如傳遞的報文的類型、格式、 有哪些字段等等。

HTTP 協議

概況

HTTP 是超文本傳輸協議,它定義了客戶端和服務器之間交換報文的格式和方式,默認使用 80 端口。它使用 TCP 作爲傳 輸層協議,保證了數據傳輸的可靠性。

HTTP 是一個無狀態的協議,HTTP 服務器不會保存關於客戶的任何信息。

HTTP 有兩種連接模式,一種是持續連接,一種非持續連接。非持續連接指的是服務器必須爲每一個請求的對象建立和維護 一個全新的連接。持續連接下,TCP 連接默認不關閉,可以被多個請求複用。採用持續連接的好處是可以避免每次建立 TCP 連接三次握手時所花費的時間。在 HTTP1.0 以前使用的非持續的連接,但是可以在請求時,加上 Connection: keep-a live 來要求服務器不要關閉 TCP 連接。HTTP1.1 以後默認採用的是持續的連接。目前對於同一個域,大多數瀏覽器支持 同時建立 6 個持久連接。

HTTP 請求報文

HTTP 報文有兩種,一種是請求報文,一種是響應報文。

HTTP 請求報文的格式如下:

GET / HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*

HTTP 請求報文的第一行叫做請求行,後面的行叫做首部行,首部行後還可以跟一個實體主體。請求首部之後有一個空行,這 個空行不能省略,它用來劃分首部與實體。

請求行包含三個字段:方法字段、URL 字段和 HTTP 版本字段。

方法字段可以取幾種不同的值,一般有 GET、POST、HEAD、PUT 和 DELETE。一般 GET 方法只被用於向服務器獲取數據。 POST 方法用於將實體提交到指定的資源,通常會造成服務器資源的修改。HEAD 方法與 GET 方法類似,但是在返回的響應 中,不包含請求對象。PUT 方法用於上傳文件到服務器,DELETE 方法用於刪除服務器上的對象。雖然請求的方法很多,但 更多表達的是一種語義上的區別,並不是說 POST 能做的事情,GET 就不能做了,主要看我們如何選擇。更多的方法可以參 看文檔

HTTP 響應報文

HTTP 報文有兩種,一種是請求報文,一種是響應報文。

HTTP 響應報文的格式如下:

HTTP/1.0 200 OK 
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84

<html>
  <body>Hello World</body>
</html>

HTTP 響應報文的第一行叫做狀態行,後面的行是首部行,最後是實體主體。

狀態行包含了三個字段:協議版本字段、狀態碼和相應的狀態信息。

實體部分是報文的主要部分,它包含了所請求的對象。

常見的狀態有

200-請求成功、202-服務器端已經收到請求消息,但是尚未進行處理 301-永久移動、302-臨時移動、304-所請求的資源未修改、 400-客戶端請求的語法錯誤、404-請求的資源不存在 500-服務器內部錯誤。

一般 1XX 代表服務器接收到請求、2XX 代表成功、3XX 代表重定向、4XX 代表客戶端錯誤、5XX 代表服務器端錯誤。

更多關於狀態碼的可以查看:

《HTTP 狀態碼》

首部行

首部可以分爲四種首部,請求首部、響應首部、通用首部和實體首部。通用首部和實體首部在請求報文和響應報文中都可以設 置,區別在於請求首部和響應首部。

常見的請求首部有 Accept 可接收媒體資源的類型、Accept-Charset 可接收的字符集、Host 請求的主機名。

常見的響應首部有 ETag 資源的匹配信息,Location 客戶端重定向的 URI。

常見的通用首部有 Cache-Control 控制緩存策略、Connection 管理持久連接。

常見的實體首部有 Content-Length 實體主體的大小、Expires 實體主體的過期時間、Last-Modified 資源的最後修 改時間。

更多關於首部的資料可以查看:

《HTTP 首部字段詳細介紹》

《圖解HTTP》

HTTP/1.1 協議缺點

HTTP/1.1 默認使用了持久連接,多個請求可以複用同一個 TCP 連接,但是在同一個 TCP 連接裏面,數據請求的通信次序 是固定的。服務器只有處理完一個請求的響應後,纔會進行下一個請求的處理,如果前面請求的響應特別慢的話,就會造成許 多請求排隊等待的情況,這種情況被稱爲“隊頭堵塞”。隊頭阻塞會導致持久連接在達到最大數量時,剩餘的資源需要等待其他 資源請求完成後才能發起請求。

爲了避免這個問題,一個是減少請求數,一個是同時打開多個持久連接。這就是我們對網站優化時,使用雪碧圖、合併腳本的 原因。

HTTP/2 協議

2009年,谷歌公開了自行研發的 SPDY 協議,主要解決 HTTP/1.1 效率不高的問題。這個協議在 Chrome 瀏覽器上證明 可行以後,就被當作 HTTP/2 的基礎,主要特性都在 HTTP/2 之中得到繼承。2015年,HTTP/2 發佈。

HTTP/2 主要有以下新的特性:

二進制協議

HTTP/2 是一個二進制協議。在 HTTP/1.1 版中,報文的頭信息必須是文本(ASCII編碼),數據體可以是文本,也可以是 二進制。HTTP/2 則是一個徹底的二進制協議,頭信息和數據體都是二進制,並且統稱爲"幀",可以分爲頭信息幀和數據幀。 幀的概念是它實現多路複用的基礎。

多路複用

HTTP/2 實現了多路複用,HTTP/2 仍然複用 TCP 連接,但是在一個連接裏,客戶端和服務器都可以同時發送多個請求或回 應,而且不用按照順序一一發送,這樣就避免了"隊頭堵塞"的問題。

數據流

HTTP/2 使用了數據流的概念,因爲 HTTP/2 的數據包是不按順序發送的,同一個連接裏面連續的數據包,可能屬於不同的 請求。因此,必須要對數據包做標記,指出它屬於哪個請求。HTTP/2 將每個請求或迴應的所有數據包,稱爲一個數據流。每 個數據流都有一個獨一無二的編號。數據包發送的時候,都必須標記數據流 ID ,用來區分它屬於哪個數據流。

頭信息壓縮

HTTP/2 實現了頭信息壓縮,由於 HTTP 1.1 協議不帶有狀態,每次請求都必須附上所有信息。所以,請求的很多字段都是 重複的,比如 Cookie 和 User Agent ,一模一樣的內容,每次請求都必須附帶,這會浪費很多帶寬,也影響速度。

HTTP/2 對這一點做了優化,引入了頭信息壓縮機制。一方面,頭信息使用 gzip 或 compress 壓縮後再發送;另一方面, 客戶端和服務器同時維護一張頭信息表,所有字段都會存入這個表,生成一個索引號,以後就不發送同樣字段了,只發送索引 號,這樣就能提高速度了。

服務器推送

HTTP/2 允許服務器未經請求,主動向客戶端發送資源,這叫做服務器推送。使用服務器推送,提前給客戶端推送必要的資源 ,這樣就可以相對減少一些延遲時間。這裏需要注意的是 http2 下服務器主動推送的是靜態資源,和 WebSocket 以及使用 SSE 等方式向客戶端發送即時數據的推送是不同的。

詳細的資料可以參考: 《HTTP 協議入門》 《HTTP/2 服務器推送(Server Push)教程》

HTTP/2 協議缺點

因爲 HTTP/2 使用了多路複用,一般來說同一域名下只需要使用一個 TCP 連接。由於多個數據流使用同一個 TCP 連接,遵 守同一個流量狀態控制和擁塞控制。只要一個數據流遭遇到擁塞,剩下的數據流就沒法發出去,這樣就導致了後面的所有數據都 會被阻塞。HTTP/2 出現的這個問題是由於其使用 TCP 協議的問題,與它本身的實現其實並沒有多大關係。

HTTP/3 協議

由於 TCP 本身存在的一些限制,Google 就開發了一個基於 UDP 協議的 QUIC 協議,並且使用在了 HTTP/3 上。 QUIC 協議在 UDP 協議上實現了多路複用、有序交付、重傳等等功能

詳細資料可以參考: 《如何看待 HTTP/3 ?》

HTTPS 協議

HTTP 存在的問題

  1. HTTP 報文使用明文方式發送,可能被第三方竊聽。
  2. HTTP 報文可能被第三方截取後修改通信內容,接收方沒有辦法發現報文內容的修改。
  3. HTTP 還存在認證的問題,第三方可以冒充他人蔘與通信。

HTTPS 簡介

HTTPS 指的是超文本傳輸安全協議,HTTPS 是基於 HTTP 協議的,不過它會使用 TLS/SSL 來對數據加密。使用 TLS/ SSL 協議,所有的信息都是加密的,第三方沒有辦法竊聽。並且它提供了一種校驗機制,信息一旦被篡改,通信的雙方會立 刻發現。它還配備了身份證書,防止身份被冒充的情況出現。

TLS 握手過程

  1. 第一步,客戶端向服務器發起請求,請求中包含使用的協議版本號、生成的一個隨機數、以及客戶端支持的加密方法。
  2. 第二步,服務器端接收到請求後,確認雙方使用的加密方法、並給出服務器的證書、以及一個服務器生成的隨機數。
  3. 第三步,客戶端確認服務器證書有效後,生成一個新的隨機數,並使用數字證書中的公鑰,加密這個隨機數,然後發給服 務器。並且還會提供一個前面所有內容的 hash 的值,用來供服務器檢驗。
  4. 第四步,服務器使用自己的私鑰,來解密客戶端發送過來的隨機數。並提供前面所有內容的 hash 值來供客戶端檢驗。
  5. 第五步,客戶端和服務器端根據約定的加密方法使用前面的三個隨機數,生成對話祕鑰,以後的對話過程都使用這個祕鑰 來加密信息。

實現原理

TLS 的握手過程主要用到了三個方法來保證傳輸的安全。

首先是對稱加密的方法,對稱加密的方法是,雙方使用同一個祕鑰對數據進行加密和解密。但是對稱加密的存在一個問題,就 是如何保證祕鑰傳輸的安全性,因爲祕鑰還是會通過網絡傳輸的,一旦祕鑰被其他人獲取到,那麼整個加密過程就毫無作用了。 這就要用到非對稱加密的方法。

非對稱加密的方法是,我們擁有兩個祕鑰,一個是公鑰,一個是私鑰。公鑰是公開的,私鑰是保密的。用私鑰加密的數據,只 有對應的公鑰才能解密,用公鑰加密的數據,只有對應的私鑰才能解密。我們可以將公鑰公佈出去,任何想和我們通信的客戶, 都可以使用我們提供的公鑰對數據進行加密,這樣我們就可以使用私鑰進行解密,這樣就能保證數據的安全了。但是非對稱加 密有一個缺點就是加密的過程很慢,因此如果每次通信都使用非對稱加密的方式的話,反而會造成等待時間過長的問題。

因此我們可以使用對稱加密和非對稱加密結合的方式,因爲對稱加密的方式的缺點是無法保證祕鑰的安全傳輸,因此我們可以 非對稱加密的方式來對對稱加密的祕鑰進行傳輸,然後以後的通信使用對稱加密的方式來加密,這樣就解決了兩個方法各自存 在的問題。

但是現在的方法也不一定是安全的,因爲我們沒有辦法確定我們得到的公鑰就一定是安全的公鑰。可能存在一箇中間人,截取 了對方發給我們的公鑰,然後將他自己的公鑰發送給我們,當我們使用他的公鑰加密後發送的信息,就可以被他用自己的私鑰 解密。然後他僞裝成我們以同樣的方法向對方發送信息,這樣我們的信息就被竊取了,然而我們自己還不知道。

爲了解決這樣的問題,我們可以使用數字證書的方式,首先我們使用一種 Hash 算法來對我們的公鑰和其他信息進行加密生成 一個信息摘要,然後讓有公信力的認證中心(簡稱 CA )用它的私鑰對消息摘要加密,形成簽名。最後將原始的信息和簽名合 在一起,稱爲數字證書。當接收方收到數字證書的時候,先根據原始信息使用同樣的 Hash 算法生成一個摘要,然後使用公證 處的公鑰來對數字證書中的摘要進行解密,最後將解密的摘要和我們生成的摘要進行對比,就能發現我們得到的信息是否被更改 了。這個方法最要的是認證中心的可靠性,一般瀏覽器裏會內置一些頂層的認證中心的證書,相當於我們自動信任了他們,只有 這樣我們才能保證數據的安全。

詳細資料可以參考: 《一個故事講完 https》 《SSL/TLS 協議運行機制的概述》 《圖解 SSL/TLS 協議》 《RSA 算法原理(一)》 《RSA 算法原理(二)》 《分分鐘讓你理解 HTTPS》

DNS 協議

概況

DNS 協議提供的是一種主機名到 IP 地址的轉換服務,就是我們常說的域名系統。它是一個由分層的 DNS 服務器組成的分 布式數據庫,是定義了主機如何查詢這個分佈式數據庫的方式的應用層協議。DNS 協議運行在 UDP 協議之上,使用 53 號 端口。

域名的層級結構

域名的層級結構可以如下

主機名.次級域名.頂級域名.根域名

# 即

host.sld.tld.root

根據域名的層級結構,管理不同層級域名的服務器,可以分爲根域名服務器、頂級域名服務器和權威域名服務器。

查詢過程

DNS 的查詢過程一般爲,我們首先將 DNS 請求發送到本地 DNS 服務器,由本地 DNS 服務器來代爲請求。

  1. 從"根域名服務器"查到"頂級域名服務器"的 NS 記錄和 A 記錄( IP 地址)。
  2. 從"頂級域名服務器"查到"次級域名服務器"的 NS 記錄和 A 記錄( IP 地址)。
  3. 從"次級域名服務器"查出"主機名"的 IP 地址。

比如我們如果想要查詢 www.baidu.com 的 IP 地址,我們首先會將請求發送到本地的 DNS 服務器中,本地 DNS 服務 器會判斷是否存在該域名的緩存,如果不存在,則向根域名服務器發送一個請求,根域名服務器返回負責 .com 的頂級域名 服務器的 IP 地址的列表。然後本地 DNS 服務器再向其中一個負責 .com 的頂級域名服務器發送一個請求,負責 .com 的頂級域名服務器返回負責 .baidu 的權威域名服務器的 IP 地址列表。然後本地 DNS 服務器再向其中一個權威域名服 務器發送一個請求,最後權威域名服務器返回一個對應的主機名的 IP 地址列表。

DNS 記錄和報文

DNS 服務器中以資源記錄的形式存儲信息,每一個 DNS 響應報文一般包含多條資源記錄。一條資源記錄的具體的格式爲

(Name,Value,Type,TTL)

其中 TTL 是資源記錄的生存時間,它定義了資源記錄能夠被其他的 DNS 服務器緩存多長時間。

常用的一共有四種 Type 的值,分別是 A、NS、CNAME 和 MX ,不同 Type 的值,對應資源記錄代表的意義不同。

  1. 如果 Type = A,則 Name 是主機名,Value 是主機名對應的 IP 地址。因此一條記錄爲 A 的資源記錄,提供了標 準的主機名到 IP 地址的映射。
  2. 如果 Type = NS,則 Name 是個域名,Value 是負責該域名的 DNS 服務器的主機名。這個記錄主要用於 DNS 鏈式 查詢時,返回下一級需要查詢的 DNS 服務器的信息。
  3. 如果 Type = CNAME,則 Name 爲別名,Value 爲該主機的規範主機名。該條記錄用於向查詢的主機返回一個主機名 對應的規範主機名,從而告訴查詢主機去查詢這個主機名的 IP 地址。主機別名主要是爲了通過給一些複雜的主機名提供 一個便於記憶的簡單的別名。
  4. 如果 Type = MX,則 Name 爲一個郵件服務器的別名,Value 爲郵件服務器的規範主機名。它的作用和 CNAME 是一 樣的,都是爲了解決規範主機名不利於記憶的缺點。

遞歸查詢和迭代查詢

遞歸查詢指的是查詢請求發出後,域名服務器代爲向下一級域名服務器發出請求,最後向用戶返回查詢的最終結果。使用遞歸 查詢,用戶只需要發出一次查詢請求。

迭代查詢指的是查詢請求後,域名服務器返回單次查詢的結果。下一級的查詢由用戶自己請求。使用迭代查詢,用戶需要發出 多次的查詢請求。

一般我們向本地 DNS 服務器發送請求的方式就是遞歸查詢,因爲我們只需要發出一次請求,然後本地 DNS 服務器返回給我 們最終的請求結果。而本地 DNS 服務器向其他域名服務器請求的過程是迭代查詢的過程,因爲每一次域名服務器只返回單次 查詢的結果,下一級的查詢由本地 DNS 服務器自己進行。

DNS 緩存

DNS 緩存的原理非常簡單,在一個請求鏈中,當某個 DNS 服務器接收到一個 DNS 回答後,它能夠將回答中的信息緩存在本 地存儲器中。返回的資源記錄中的 TTL 代表了該條記錄的緩存的時間。

DNS 實現負載平衡

DNS 可以用於在冗餘的服務器上實現負載平衡。因爲現在一般的大型網站使用多臺服務器提供服務,因此一個域名可能會對應 多個服務器地址。當用戶發起網站域名的 DNS 請求的時候,DNS 服務器返回這個域名所對應的服務器 IP 地址的集合,但在 每個回答中,會循環這些 IP 地址的順序,用戶一般會選擇排在前面的地址發送請求。以此將用戶的請求均衡的分配到各個不 同的服務器上,這樣來實現負載均衡。

詳細資料可以參考: 《DNS 原理入門》 《根域名的知識》

傳輸層

傳輸層協議主要是爲不同主機上的不同進程間提供了邏輯通信的功能。傳輸層只工作在端系統中。

多路複用與多路分解

將傳輸層報文段中的數據交付到正確的套接字的工作被稱爲多路分解。

在源主機上從不同的套接字中收集數據,封裝頭信息生成報文段後,將報文段傳遞到網絡層,這個過程被稱爲多路複用。

無連接的多路複用和多路分解指的是 UDP 套接字的分配過程,一個 UDP 套接字由一個二元組來標識,這個二元組包含了一 個目的地址和一個目的端口號。因此不同源地址和端口號的 UDP 報文段到達主機後,如果它們擁有相同的目的地址和目的端 口號,那麼不同的報文段將會轉交到同一個 UDP 套接字中。

面向連接的多路複用和多路分解指的是 TCP 套接字的分配過程,一個 TCP 套接字由一個四元組來標識,這個四元組包含了 源 IP 地址、源端口號、目的地址和目的端口號。因此,一個 TCP 報文段從網絡中到達一臺主機上時,該主機使用全部4個 值來將報文段定向到相應的套接字。

UDP 協議

UDP 是一種無連接的,不可靠的傳輸層協議。它只提供了傳輸層需要實現的最低限度的功能,除了複用/分解功能和少量的差 錯檢測外,它幾乎沒有對 IP 增加其他的東西。UDP 協議適用於對實時性要求高的應用場景。

特點:

  1. 使用 UDP 時,在發送報文段之前,通信雙方沒有握手的過程,因此 UDP 被稱爲是無連接的傳輸層協議。因爲沒有握手 過程,相對於 TCP 來說,沒有建立連接的時延。因爲沒有連接,所以不需要在端系統中保存連接的狀態。
  2. UDP 提供盡力而爲的交付服務,也就是說 UDP 協議不保證數據的可靠交付。
  3. UDP 沒有擁塞控制和流量控制的機制,所以 UDP 報文段的發送速率沒有限制。
  4. 因爲一個 UDP 套接字只使用目的地址和目的端口來標識,所以 UDP 可以支持一對一、一對多、多對一和多對多的交互 通信。
  5. UDP 首部小,只有8個字節。

UDP 報文段結構

UDP 報文段由首部和應用數據組成。報文段首部包含四個字段,分別是源端口號、目的端口號、長度和檢驗和,每個字段的長 度爲兩個字節。長度字段指的是整個報文段的長度,包含了首部和應用數據的大小。校驗和是 UDP 提供的一種差錯校驗機制。 雖然提供了差錯校驗的機制,但是 UDP 對於差錯的恢復無能爲力。

UDP 報文段結構

TCP 協議

TCP 協議是面向連接的,提供可靠數據傳輸服務的傳輸層協議。

特點:

  1. TCP 協議是面向連接的,在通信雙方進行通信前,需要通過三次握手建立連接。它需要在端系統中維護雙方連接的狀態信 息。
  2. TCP 協議通過序號、確認號、定時重傳、檢驗和等機制,來提供可靠的數據傳輸服務。
  3. TCP 協議提供的是點對點的服務,即它是在單個發送方和單個接收方之間的連接。
  4. TCP 協議提供的是全雙工的服務,也就是說連接的雙方的能夠向對方發送和接收數據。
  5. TCP 提供了擁塞控制機制,在網絡擁塞的時候會控制發送數據的速率,有助於減少數據包的丟失和減輕網絡中的擁塞程度。
  6. TCP 提供了流量控制機制,保證了通信雙方的發送和接收速率相同。如果接收方可接收的緩存很小時,發送方會降低發送 速率,避免因爲緩存填滿而造成的數據包的丟失。

TCP 報文段結構

TCP 報文段由首部和數據組成,它的首部一般爲 20 個字節。

源端口和目的端口號用於報文段的多路複用和分解。

32比特的序號和32比特的確認號,用與實現可靠數據運輸服務。

16比特的接收窗口字段用於實現流量控制,該字段表示接收方願意接收的字節的數量。

4比特的首部長度字段,該字段指示了以32比特的字爲單位的 TCP 首部的長度。

6比特的標誌字段,ACK 字段用於指示確認序號的值是有效的,RST、SYN 和 FIN 比特用於連接建立和拆除。設置 PSH 字 段指示接收方應該立即將數據交給上層,URG 字段用來指示報文段裏存在緊急的數據。

校驗和提供了對數據的差錯檢測。

TCP 報文段結構

TCP 三次握手的過程

第一次握手,客戶端向服務器發送一個 SYN 連接請求報文段,報文段的首部中 SYN 標誌位置爲1,序號字段是一個任選的 隨機數。它代表的是客戶端數據的初始序號。

第二次握手,服務器端接收到客戶端發送的 SYN 連接請求報文段後,服務器首先會爲該連接分配 TCP 緩存和變量,然後向 客戶端發送 SYN ACK 報文段,報文段的首部中 SYN 和 ACK 標誌位都被置爲1,代表這是一個對 SYN 連接請求的確認, 同時序號字段是服務器端產生的一個任選的隨機數,它代表的是服務器端數據的初始序號。確認號字段爲客戶端發送的序號加 一。

第三次握手,客戶端接收到服務器的肯定應答後,它也會爲這次 TCP 連接分配緩存和變量,同時向服務器端發送一個對服務 器端的報文段的確認。第三次握手可以在報文段中攜帶數據。

在我看來,TCP 三次握手的建立連接的過程就是相互確認初始序號的過程,告訴對方,什麼樣序號的報文段能夠被正確接收。 第三次握手的作用是客戶端對服務器端的初始序號的確認。如果只使用兩次握手,那麼服務器就沒有辦法知道自己的序號是否 已被確認。同時這樣也是爲了防止失效的請求報文段被服務器接收,而出現錯誤的情況。

詳細資料可以參考: 《TCP 爲什麼是三次握手,而不是兩次或四次?》 《TCP 的三次握手與四次揮手》

TCP 四次揮手的過程

因爲 TCP 連接是全雙工的,也就是說通信的雙方都可以向對方發送和接收消息,所以斷開連接需要雙方的確認。

第一次揮手,客戶端認爲沒有數據要再發送給服務器端,它就向服務器發送一個 FIN 報文段,申請斷開客戶端到服務器端的 連接。發送後客戶端進入 FIN_WAIT_1 狀態。

第二次揮手,服務器端接收到客戶端釋放連接的請求後,向客戶端發送一個確認報文段,表示已經接收到了客戶端釋放連接的 請求,以後不再接收客戶端發送過來的數據。但是因爲連接是全雙工的,所以此時,服務器端還可以向客戶端發送數據。服務 器端進入 CLOSE_WAIT 狀態。客戶端收到確認後,進入 FIN_WAIT_2 狀態。

第三次揮手,服務器端發送完所有數據後,向客戶端發送 FIN 報文段,申請斷開服務器端到客戶端的連接。發送後進入 LAS T_ACK 狀態。

第四次揮手,客戶端接收到 FIN 請求後,向服務器端發送一個確認應答,並進入 TIME_WAIT 階段。該階段會持續一段時間, 這個時間爲報文段在網絡中的最大生存時間,如果該時間內服務端沒有重發請求的話,客戶端進入 CLOSED 的狀態。如果收到 服務器的重發請求就重新發送確認報文段。服務器端收到客戶端的確認報文段後就進入 CLOSED 狀態,這樣全雙工的連接就被 釋放了。

TCP 使用四次揮手的原因是因爲 TCP 的連接是全雙工的,所以需要雙方分別釋放到對方的連接,單獨一方的連接釋放,只代 表不能再向對方發送數據,連接處於的是半釋放的狀態。

最後一次揮手中,客戶端會等待一段時間再關閉的原因,是爲了防止發送給服務器的確認報文段丟失或者出錯,從而導致服務器 端不能正常關閉。

詳細資料可以參考:

《前端面試之道》

狀態轉化圖

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LirlKgfj-1584587730351)(https://camo.githubusercontent.com/d3812f01ceddb5619487ecb28c767183ebad867c/68747470733a2f2f636176737a686f75796f752d313235343039333639372e636f732e61702d63686f6e6771696e672e6d7971636c6f75642e636f6d2f6e6f74652d31382e706e67)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-bRH9Ia9H-1584587730351)(https://camo.githubusercontent.com/446696955fd6d6a791acd8428e43f18918ecfa4c/68747470733a2f2f636176737a686f75796f752d313235343039333639372e636f732e61702d63686f6e6771696e672e6d7971636c6f75642e636f6d2f6e6f74652d31392e706e67)]

ARQ 協議

ARQ 協議指的是自動重傳請求,它通過超時和重傳來保證數據的可靠交付,它是 TCP 協議實現可靠數據傳輸的一個很重要的 機制。

它分爲停止等待 ARQ 協議和連續 ARQ 協議。

一、停止等待 ARQ 協議

停止等待 ARQ 協議的基本原理是,對於發送方來說發送方每發送一個分組,就爲這個分組設置一個定時器。當發送分組的確認 回答返回了,則清除定時器,發送下一個分組。如果在規定的時間內沒有收到已發送分組的肯定回答,則重新發送上一個分組。

對於接受方來說,每次接受到一個分組,就返回對這個分組的肯定應答,當收到冗餘的分組時,就直接丟棄,並返回一個對冗餘 分組的確認。當收到分組損壞的情況的時候,直接丟棄。

使用停止等待 ARQ 協議的缺點是每次發送分組必須等到分組確認後才能發送下一個分組,這樣會造成信道的利用率過低。

二、連續 ARQ 協議

連續 ARQ 協議是爲了解決停止等待 ARQ 協議對於信道的利用率過低的問題。它通過連續發送一組分組,然後再等待對分組的 確認回答,對於如何處理分組中可能出現的差錯恢復情況,一般可以使用滑動窗口協議和選擇重傳協議來實現。

  1. 滑動窗口協議

    使用滑動窗口協議,在發送方維持了一個發送窗口,發送窗口以前的分組是已經發送並確認了的分組,發送窗口中包含了已經發 送但未確認的分組和允許發送但還未發送的分組,發送窗口以後的分組是緩存中還不允許發送的分組。當發送方向接收方發送分 組時,會依次發送窗口內的所有分組,並且設置一個定時器,這個定時器可以理解爲是最早發送但未收到確認的分組。如果在定 時器的時間內收到某一個分組的確認回答,則滑動窗口,將窗口的首部移動到確認分組的後一個位置,此時如果還有已發送但沒 有確認的分組,則重新設置定時器,如果沒有了則關閉定時器。如果定時器超時,則重新發送所有已經發送但還未收到確認的分 組。

    接收方使用的是累計確認的機制,對於所有按序到達的分組,接收方返回一個分組的肯定回答。如果收到了一個亂序的分組,那 麼接方會直接丟棄,並返回一個最近的按序到達的分組的肯定回答。使用累計確認保證了確認號以前的分組都已經按序到達了, 所以發送窗口可以移動到已確認分組的後面。

    滑動窗口協議的缺點是因爲使用了累計確認的機制,如果出現了只是窗口中的第一個分組丟失,而後面的分組都按序到達的情況 的話,那麼滑動窗口協議會重新發送所有的分組,這樣就造成了大量不必要分組的丟棄和重傳。

  2. 選擇重傳協議

    因爲滑動窗口使用累計確認的方式,所以會造成很多不必要分組的重傳。使用選擇重傳協議可以解決這個問題。

    選擇重傳協議在發送方維護了一個發送窗口。發送窗口的以前是已經發送並確認的分組,窗口內包含了已發送但未被確認的分組, 已確認的亂序分組,和允許發送但還未發送的分組,發送窗口以後的是緩存中還不允許發送的分組。選擇重傳協議與滑動窗口協 議最大的不同是,發送方發送分組時,爲一個分組都創建了一個定時器。當發送方接受到一個分組的確認應答後,取消該分組的 定時器,並判斷接受該分組後,是否存在由窗口首部爲首的連續的確認分組,如果有則向後移動窗口的位置,如果沒有則將該分 組標識爲已接收的亂序分組。當某一個分組定時器到時後,則重新傳遞這個分組。

    在接收方,它會確認每一個正確接收的分組,不管這個分組是按序的還是亂序的,亂序的分組將被緩存下來,直到所有的亂序分 組都到達形成一個有序序列後,再將這一段分組交付給上層。對於不能被正確接收的分組,接收方直接忽略該分組。

詳細資料可以參考: 《TCP 連續 ARQ 協議和滑動窗口協議》

TCP 的可靠運輸機制

TCP 的可靠運輸機制是基於連續 ARQ 協議和滑動窗口協議的。

TCP 協議在發送方維持了一個發送窗口,發送窗口以前的報文段是已經發送並確認了的報文段,發送窗口中包含了已經發送但 未確認的報文段和允許發送但還未發送的報文段,發送窗口以後的報文段是緩存中還不允許發送的報文段。當發送方向接收方發 送報文時,會依次發送窗口內的所有報文段,並且設置一個定時器,這個定時器可以理解爲是最早發送但未收到確認的報文段。 如果在定時器的時間內收到某一個報文段的確認回答,則滑動窗口,將窗口的首部向後滑動到確認報文段的後一個位置,此時如 果還有已發送但沒有確認的報文段,則重新設置定時器,如果沒有了則關閉定時器。如果定時器超時,則重新發送所有已經發送 但還未收到確認的報文段,並將超時的間隔設置爲以前的兩倍。當發送方收到接收方的三個冗餘的確認應答後,這是一種指示, 說明該報文段以後的報文段很有可能發生丟失了,那麼發送方會啓用快速重傳的機制,就是當前定時器結束前,發送所有的已發 送但確認的報文段。

接收方使用的是累計確認的機制,對於所有按序到達的報文段,接收方返回一個報文段的肯定回答。如果收到了一個亂序的報文 段,那麼接方會直接丟棄,並返回一個最近的按序到達的報文段的肯定回答。使用累計確認保證了返回的確認號之前的報文段都 已經按序到達了,所以發送窗口可以移動到已確認報文段的後面。

發送窗口的大小是變化的,它是由接收窗口剩餘大小和網絡中擁塞程度來決定的,TCP 就是通過控制發送窗口的長度來控制報文 段的發送速率。

但是 TCP 協議並不完全和滑動窗口協議相同,因爲許多的 TCP 實現會將失序的報文段給緩存起來,並且發生重傳時,只會重 傳一個報文段,因此 TCP 協議的可靠傳輸機制更像是窗口滑動協議和選擇重傳協議的一個混合體。

TCP 的流量控制機制

TCP 提供了流量控制的服務,這個服務的主要目的是控制發送方的發送速率,保證接收方來得及接收。因爲一旦發送的速率大 於接收方所能接收的速率,就會造成報文段的丟失。接收方主要是通過接收窗口來告訴發送方自己所能接收的大小,發送方根據 接收方的接收窗口的大小來調整發送窗口的大小,以此來達到控制發送速率的目的。

TCP 的擁塞控制機制

TCP 的擁塞控制主要是根據網絡中的擁塞情況來控制發送方數據的發送速率,如果網絡處於擁塞的狀態,發送方就減小發送的 速率,這樣一方面是爲了避免繼續增加網絡中的擁塞程度,另一方面也是爲了避免網絡擁塞可能造成的報文段丟失。

TCP 的擁塞控制主要使用了四個機制,分別是慢啓動、擁塞避免、快速重傳和快速恢復。

慢啓動的基本思想是,因爲在發送方剛開始發送數據的時候,並不知道網絡中的擁塞程度,所以先以較低的速率發送,進行試探 ,每次收到一個確認報文,就將發動窗口的長度加一,這樣每個 RTT 時間後,發送窗口的長度就會加倍。當發送窗口的大小達 到一個閾值的時候就進入擁塞避免算法。

擁塞避免算法是爲了避免可能發生的擁塞,將發送窗口的大小由每過一個 RTT 增長一倍,變爲每過一個 RTT ,長度只加一。 這樣將窗口的增長速率由指數增長,變爲加法線性增長。

快速重傳指的是,當發送方收到三個冗餘的確認應答時,因爲 TCP 使用的是累計確認的機制,所以很有可能是發生了報文段的 丟失,因此採用立即重傳的機制,在定時器結束前發送所有已發送但還未接收到確認應答的報文段。

快速恢復是對快速重傳的後續處理,因爲網絡中可能已經出現了擁塞情況,所以會將慢啓動的閥值減小爲原來的一半,然後將擁 塞窗口的值置爲減半後的閥值,然後開始執行擁塞避免算法,使得擁塞窗口緩慢地加性增大。簡單來理解就是,乘性減,加性增。

TCP 認爲網絡擁塞的主要依據是報文段的重傳次數,它會根據網絡中的擁塞程度,通過調整慢啓動的閥值,然後交替使用上面四 種機制來達到擁塞控制的目的。

詳細資料可以參考: 《TCP 的擁塞控制機制》 《網絡基本功:TCP 擁塞控制機制》

網絡層

網絡層協議主要實現了不同主機間的邏輯通信功能。網絡層協議一共包含兩個主要的組件,一個 IP 網際協議,一個是路由選 擇協議。

IP 網際協議規定了網絡層的編址和轉發方式,比如說我們接入網絡的主機都會被分配一個 IP 地址,常用的比如 IPV4 使用 32位來分配地址,還有 IPv6 使用128位來分配地址。

路由選擇協議決定了數據報從源到目的地所流經的路徑,常見的比如距離向量路由選擇算法等。

數據鏈路層

數據鏈路層提供的服務是如何將數據報通過單一通信鏈路從一個結點移動到相鄰節點。每一臺主機都有一個唯一的 MAC 地址, 這是由網絡適配器決定的,在全世界都是獨一無二的。

物理層

物理層提供的服務是儘可能的屏蔽掉組成網絡的物理設備和傳輸介質間的差異,使數據鏈路層不需要考慮網絡的具體傳輸介質 是什麼。

詳細資料可以參考: 《搞定計算機網絡面試,看這篇就夠了(補充版)》 《互聯網協議入門(一)》 《互聯網協議入門(二)》

常考面試題

1. Post 和 Get 的區別?

Post 和 Get 是 HTTP 請求的兩種方法。

(1)從應用場景上來說,GET 請求是一個冪等的請求,一般 Get 請求用於對服務器資源不會產生影響的場景,比如說請求一個網
    頁。而 Post 不是一個冪等的請求,一般用於對服務器資源會產生影響的情景。比如註冊用戶這一類的操作。
    
(2)因爲不同的應用場景,所以瀏覽器一般會對 Get 請求緩存,但很少對 Post 請求緩存。

(3)從發送的報文格式來說,Get 請求的報文中實體部分爲空,Post 請求的報文中實體部分一般爲向服務器發送的數據。

(4)但是 Get 請求也可以將請求的參數放入 url 中向服務器發送,這樣的做法相對於 Post 請求來說,一個方面是不太安全,
    因爲請求的 url 會被保留在歷史記錄中。並且瀏覽器由於對 url 有一個長度上的限制,所以會影響 get 請求發送數據時
    的長度。這個限制是瀏覽器規定的,並不是 RFC 規定的。還有就是 post 的參數傳遞支持更多的數據類型。

2. TLS/SSL 中什麼一定要用三個隨機數,來生成"會話密鑰"?

客戶端和服務器都需要生成隨機數,以此來保證每次生成的祕鑰都不相同。使用三個隨機數,是因爲 SSL 的協議默認不信任每個主
機都能產生完全隨機的數,如果只使用一個僞隨機的數來生成祕鑰,就很容易被破解。通過使用三個隨機數的方式,增加了自由度,
一個僞隨機可能被破解,但是三個僞隨機就很接近於隨機了,因此可以使用這種方法來保持生成祕鑰的隨機性和安全性。

3. SSL 連接斷開後如何恢復?

一共有兩種方法來恢復斷開的 SSL 連接,一種是使用 session ID,一種是 session ticket。

使用 session ID 的方式,每一次的會話都有一個編號,當對話中斷後,下一次重新連接時,只要客戶端給出這個編號,服務器
如果有這個編號的記錄,那麼雙方就可以繼續使用以前的祕鑰,而不用重新生成一把。目前所有的瀏覽器都支持這一種方法。但是
這種方法有一個缺點是,session ID 只能夠存在一臺服務器上,如果我們的請求通過負載平衡被轉移到了其他的服務器上,那
麼就無法恢復對話。

另一種方式是 session ticket 的方式,session ticket 是服務器在上一次對話中發送給客戶的,這個 ticket 是加密的
,只有服務器能夠解密,裏面包含了本次會話的信息,比如對話祕鑰和加密方法等。這樣不管我們的請求是否轉移到其他的服務器
上,當服務器將 ticket 解密以後,就能夠獲取上次對話的信息,就不用重新生成對話祕鑰了。

4. RSA 算法的安全性保障?

對極大整數做因數分解的難度決定了 RSA 算法的可靠性。換言之,對一極大整數做因數分解愈困難,RSA 算法愈可靠。現在102
4位的 RSA 密鑰基本安全,2048位的密鑰極其安全。

5. DNS 爲什麼使用 UDP 協議作爲傳輸層協議?

DNS 使用 UDP 協議作爲傳輸層協議的主要原因是爲了避免使用 TCP 協議時造成的連接時延。因爲爲了得到一個域名的 IP 地
址,往往會向多個域名服務器查詢,如果使用 TCP 協議,那麼每次請求都會存在連接時延,這樣使 DNS 服務變得很慢,因爲大
多數的地址查詢請求,都是瀏覽器請求頁面時發出的,這樣會造成網頁的等待時間過長。

使用 UDP 協議作爲 DNS 協議會有一個問題,由於歷史原因,物理鏈路的最小MTU = 576,所以爲了限制報文長度不超過576,
UDP 的報文段的長度被限制在 512 個字節以內,這樣一旦 DNS 的查詢或者應答報文,超過了 512 字節,那麼基於 UDP 的
DNS 協議就會被截斷爲 512 字節,那麼有可能用戶得到的 DNS 應答就是不完整的。這裏 DNS 報文的長度一旦超過限制,並不
會像 TCP 協議那樣被拆分成多個報文段傳輸,因爲 UDP 協議不會維護連接狀態,所以我們沒有辦法確定那幾個報文段屬於同一
個數據,UDP 只會將多餘的數據給截取掉。爲了解決這個問題,我們可以使用 TCP 協議去請求報文。

DNS 還存在的一個問題是安全問題,就是我們沒有辦法確定我們得到的應答,一定是一個安全的應答,因爲應答可以被他人僞造,
所以現在有了 DNS over HTTPS 來解決這個問題。

詳細資料可以參考: 《爲什麼 DNS 使用 UDP 而不是 TCP?》

6. 當你在瀏覽器中輸入 Google.com 並且按下回車之後發生了什麼?

(1)首先會對 URL 進行解析,分析所需要使用的傳輸協議和請求的資源的路徑。如果輸入的 URL 中的協議或者主機名不合法,
    將會把地址欄中輸入的內容傳遞給搜索引擎。如果沒有問題,瀏覽器會檢查 URL 中是否出現了非法字符,如果存在非法字
    符,則對非法字符進行轉義後再進行下一過程。

(2)瀏覽器會判斷所請求的資源是否在緩存裏,如果請求的資源在緩存裏並且沒有失效,那麼就直接使用,否則向服務器發起新
    的請求。

(3)下一步我們首先需要獲取的是輸入的 URL 中的域名的 IP 地址,首先會判斷本地是否有該域名的 IP 地址的緩存,如果
    有則使用,如果沒有則向本地 DNS 服務器發起請求。本地 DNS 服務器也會先檢查是否存在緩存,如果沒有就會先向根域
    名服務器發起請求,獲得負責的頂級域名服務器的地址後,再向頂級域名服務器請求,然後獲得負責的權威域名服務器的地
    址後,再向權威域名服務器發起請求,最終獲得域名的 IP 地址後,本地 DNS 服務器再將這個 IP 地址返回給請求的用
    戶。用戶向本地 DNS 服務器發起請求屬於遞歸請求,本地 DNS 服務器向各級域名服務器發起請求屬於迭代請求。

(4)當瀏覽器得到 IP 地址後,數據傳輸還需要知道目的主機 MAC 地址,因爲應用層下發數據給傳輸層,TCP 協議會指定源
    端口號和目的端口號,然後下發給網絡層。網絡層會將本機地址作爲源地址,獲取的 IP 地址作爲目的地址。然後將下發給
    數據鏈路層,數據鏈路層的發送需要加入通信雙方的 MAC 地址,我們本機的 MAC 地址作爲源 MAC 地址,目的 MAC 地
    址需要分情況處理,通過將 IP 地址與我們本機的子網掩碼相與,我們可以判斷我們是否與請求主機在同一個子網裏,如果
    在同一個子網裏,我們可以使用 APR 協議獲取到目的主機的 MAC 地址,如果我們不在一個子網裏,那麼我們的請求應該
    轉發給我們的網關,由它代爲轉發,此時同樣可以通過 ARP 協議來獲取網關的 MAC 地址,此時目的主機的 MAC 地址應
    該爲網關的地址。

(5)下面是 TCP 建立連接的三次握手的過程,首先客戶端向服務器發送一個 SYN 連接請求報文段和一個隨機序號,服務端接
    收到請求後向服務器端發送一個 SYN ACK報文段,確認連接請求,並且也向客戶端發送一個隨機序號。客戶端接收服務器的
    確認應答後,進入連接建立的狀態,同時向服務器也發送一個 ACK 確認報文段,服務器端接收到確認後,也進入連接建立
    狀態,此時雙方的連接就建立起來了。

(6)如果使用的是 HTTPS 協議,在通信前還存在 TLS 的一個四次握手的過程。首先由客戶端向服務器端發送使用的協議的版
    本號、一個隨機數和可以使用的加密方法。服務器端收到後,確認加密的方法,也向客戶端發送一個隨機數和自己的數字證
    書。客戶端收到後,首先檢查數字證書是否有效,如果有效,則再生成一個隨機數,並使用證書中的公鑰對隨機數加密,然後
    發送給服務器端,並且還會提供一個前面所有內容的 hash 值供服務器端檢驗。服務器端接收後,使用自己的私鑰對數據解
    密,同時向客戶端發送一個前面所有內容的 hash 值供客戶端檢驗。這個時候雙方都有了三個隨機數,按照之前所約定的加
    密方法,使用這三個隨機數生成一把祕鑰,以後雙方通信前,就使用這個祕鑰對數據進行加密後再傳輸。

(7)當頁面請求發送到服務器端後,服務器端會返回一個 html 文件作爲響應,瀏覽器接收到響應後,開始對 html 文件進行
    解析,開始頁面的渲染過程。

(8)瀏覽器首先會根據 html 文件構建 DOM 樹,根據解析到的 css 文件構建 CSSOM 樹,如果遇到 script 標籤,則判端
    是否含有 defer 或者 async 屬性,要不然 script 的加載和執行會造成頁面的渲染的阻塞。當 DOM 樹和 CSSOM 樹建
    立好後,根據它們來構建渲染樹。渲染樹構建好後,會根據渲染樹來進行佈局。佈局完成後,最後使用瀏覽器的 UI 接口對頁
    面進行繪製。這個時候整個頁面就顯示出來了。

(9)最後一步是 TCP 斷開連接的四次揮手過程。

詳細資料可以參考: 《當你在瀏覽器中輸入 Google.com 並且按下回車之後發生了什麼?》

7. 談談 CDN 服務?

CDN 是一個內容分發網絡,通過對源網站資源的緩存,利用本身多臺位於不同地域、不同運營商的服務器,向用戶提供資就近訪問的
功能。也就是說,用戶的請求並不是直接發送給源網站,而是發送給 CDN 服務器,由 CND 服務器將請求定位到最近的含有該資源
的服務器上去請求。這樣有利於提高網站的訪問速度,同時通過這種方式也減輕了源服務器的訪問壓力。

詳細資料可以參考: 《CDN 是什麼?使用 CDN 有什麼優勢?》

8. 什麼是正向代理和反向代理?

我們常說的代理也就是指正向代理,正向代理的過程,它隱藏了真實的請求客戶端,服務端不知道真實的客戶端是誰,客戶端請求的
服務都被代理服務器代替來請求。

反向代理隱藏了真實的服務端,當我們請求一個網站的時候,背後可能有成千上萬臺服務器爲我們服務,但具體是哪一臺,我們不知
道,也不需要知道,我們只需要知道反向代理服務器是誰就好了,反向代理服務器會幫我們把請求轉發到真實的服務器那裏去。反向
代理器一般用來實現負載平衡。

詳細資料可以參考: 《正向代理與反向代理有什麼區別》 《webpack 配置 proxy 反向代理的原理是什麼?》

9. 負載平衡的兩種實現方式?

一種是使用反向代理的方式,用戶的請求都發送到反向代理服務上,然後由反向代理服務器來轉發請求到真實的服務器上,以此來實
現集羣的負載平衡。

另一種是 DNS 的方式,DNS 可以用於在冗餘的服務器上實現負載平衡。因爲現在一般的大型網站使用多臺服務器提供服務,因此一
個域名可能會對應多個服務器地址。當用戶向網站域名請求的時候,DNS 服務器返回這個域名所對應的服務器 IP 地址的集合,但在
每個回答中,會循環這些 IP 地址的順序,用戶一般會選擇排在前面的地址發送請求。以此將用戶的請求均衡的分配到各個不同的服
務器上,這樣來實現負載均衡。這種方式有一個缺點就是,由於 DNS 服務器中存在緩存,所以有可能一個服務器出現故障後,域名解
析仍然返回的是那個 IP 地址,就會造成訪問的問題。

詳細資料可以參考: 《負載均衡的原理》

10. http 請求方法 options 方法有什麼用?

 OPTIONS 請求與 HEAD 類似,一般也是用於客戶端查看服務器的性能。這個方法會請求服務器返回該資源所支持的所有 HTTP 請
 求方法,該方法會用'*'來代替資源名稱,向服務器發送 OPTIONS 請求,可以測試服務器功能是否正常。JS 的 XMLHttpRequest
 對象進行 CORS 跨域資源共享時,對於複雜請求,就是使用 OPTIONS 方法發送嗅探請求,以判斷是否有對指定資源的訪問權限。

相關資料可以參考: 《HTTP 請求方法》

11. http1.1 和 http1.0 之間有哪些區別?

 http1.1 相對於 http1.0 有這樣幾個區別:

 (1)連接方面的區別,http1.1 默認使用持久連接,而 http1.0 默認使用非持久連接。http1.1 通過使用持久連接來使多個
     http 請求複用同一個 TCP 連接,以此來避免使用非持久連接時每次需要建立連接的時延。

 (2)資源請求方面的區別,在 http1.0 中,存在一些浪費帶寬的現象,例如客戶端只是需要某個對象的一部分,而服務器卻將整個
     對象送過來了,並且不支持斷點續傳功能,http1.1 則在請求頭引入了 range 頭域,它允許只請求資源的某個部分,即返回碼
     是 206(Partial Content),這樣就方便了開發者自由的選擇以便於充分利用帶寬和連接。

 (3)緩存方面的區別,在 http1.0 中主要使用 header 裏的 If-Modified-Since,Expires 來做爲緩存判斷的標準,http1.1
     則引入了更多的緩存控制策略例如 Etag、If-Unmodified-Since、If-Match、If-None-Match 等更多可供選擇的緩存頭來
     控制緩存策略。

 (4)http1.1 中還新增了 host 字段,用來指定服務器的域名。http1.0 中認爲每臺服務器都綁定一個唯一的 IP 地址,因此,
     請求消息中的 URL 並沒有傳遞主機名(hostname)。但隨着虛擬主機技術的發展,在一臺物理服務器上可以存在多個虛擬主機
     ,並且它們共享一個IP地址。因此有了 host 字段,就可以將請求發往同一臺服務器上的不同網站。

 (5)http1.1 相對於 http1.0 還新增了很多方法,如 PUT、HEAD、OPTIONS 等。
 

詳細資料可以參考: 《HTTP1.0、HTTP1.1 和 HTTP2.0 的區別》 《HTTP 協議入門》 《網絡—一篇文章詳解請求頭 Host 的概念》

12. 網站域名加 www 與不加 www 的區別?

詳細資料可以參考: 《爲什麼域名前要加 www 前綴 www 是什麼意思?》 《爲什麼越來越多的網站域名不加「www」前綴?》 《域名有 www 與沒有 www 有什麼區別?》

13. 即時通訊的實現,短輪詢、長輪詢、SSE 和 WebSocket 間的區別?

 短輪詢和長輪詢的目的都是用於實現客戶端和服務器端的一個即時通訊。

 短輪詢的基本思路就是瀏覽器每隔一段時間向瀏覽器發送 http 請求,服務器端在收到請求後,不論是否有數據更新,都直接進行
 響應。這種方式實現的即時通信,本質上還是瀏覽器發送請求,服務器接受請求的一個過程,通過讓客戶端不斷的進行請求,使得客
 戶端能夠模擬實時地收到服務器端的數據的變化。這種方式的優點是比較簡單,易於理解。缺點是這種方式由於需要不斷的建立 ht
 tp 連接,嚴重浪費了服務器端和客戶端的資源。當用戶增加時,服務器端的壓力就會變大,這是很不合理的。

 長輪詢的基本思路是,首先由客戶端向服務器發起請求,當服務器收到客戶端發來的請求後,服務器端不會直接進行響應,而是先將
 這個請求掛起,然後判斷服務器端數據是否有更新。如果有更新,則進行響應,如果一直沒有數據,則到達一定的時間限制才返回。
 客戶端 JavaScript 響應處理函數會在處理完服務器返回的信息後,再次發出請求,重新建立連接。長輪詢和短輪詢比起來,它的
 優點是明顯減少了很多不必要的 http 請求次數,相比之下節約了資源。長輪詢的缺點在於,連接掛起也會導致資源的浪費。

 SSE 的基本思想是,服務器使用流信息向服務器推送信息。嚴格地說,http 協議無法做到服務器主動推送信息。但是,有一種變通
 方法,就是服務器向客戶端聲明,接下來要發送的是流信息。也就是說,發送的不是一次性的數據包,而是一個數據流,會連續不斷
 地發送過來。這時,客戶端不會關閉連接,會一直等着服務器發過來的新的數據流,視頻播放就是這樣的例子。SSE 就是利用這種機
 制,使用流信息向瀏覽器推送信息。它基於 http 協議,目前除了 IE/Edge,其他瀏覽器都支持。它相對於前面兩種方式來說,不
 需要建立過多的 http 請求,相比之下節約了資源。

 上面三種方式本質上都是基於 http 協議的,我們還可以使用 WebSocket 協議來實現。WebSocket 是 Html5 定義的一個新協
 議,與傳統的 http 協議不同,該協議允許由服務器主動的向客戶端推送信息。使用 WebSocket 協議的缺點是在服務器端的配置
 比較複雜。WebSocket 是一個全雙工的協議,也就是通信雙方是平等的,可以相互發送消息,而 SSE 的方式是單向通信的,只能
 由服務器端向客戶端推送信息,如果客戶端需要發送信息就是屬於下一個 http 請求了。

詳細資料可以參考: 《輪詢、長輪詢、長連接、websocket》 《Server-Sent Events 教程》 《WebSocket 教程》

14. 怎麼實現多個網站之間共享登錄狀態

 在多個網站之間共享登錄狀態指的就是單點登錄。多個應用系統中,用戶只需要登錄一次就可以訪問所有相互信任的應用系統。

 我認爲單點登錄可以這樣來實現,首先將用戶信息的驗證中心獨立出來,作爲一個單獨的認證中心,該認證中心的作用是判斷客戶端發
 送的賬號密碼的正確性,然後向客戶端返回對應的用戶信息,並且返回一個由服務器端祕鑰加密的登錄信息的 token 給客戶端,該
 token 具有一定的有效時限。當一個應用系統跳轉到另一個應用系統時,通過 url 參數的方式來傳遞 token,然後轉移到的應用站
 點發送給認證中心,認證中心對 token 進行解密後驗證,如果用戶信息沒有失效,則向客戶端返回對應的用戶信息,如果失效了則將
 頁面重定向會單點登錄頁面。

詳細資料可以參考: 《HTTP 是個無狀態協議,怎麼保持登錄狀態?》


常用工具知識總結

本部分主要是筆者關於常用工具所做的筆記,如果出現錯誤,希望大家指出!

目錄

GIT

1. git 與 svn 的區別在哪裏?

git 和 svn 最大的區別在於 git 是分佈式的,而 svn 是集中式的。因此我們不能再離線的情況下使用 svn。如果服務器
出現問題,我們就沒有辦法使用 svn 來提交我們的代碼。

svn 中的分支是整個版本庫的複製的一份完整目錄,而 git 的分支是指針指向某次提交,因此 git 的分支創建更加開銷更小
並且分支上的變化不會影響到其他人。svn 的分支變化會影響到所有的人。

svn 的指令相對於 git 來說要簡單一些,比 git 更容易上手。

詳細資料可以參考: 《常見工作流比較》 《對比 Git 與 SVN,這篇講的很易懂》 《GIT 與 SVN 世紀大戰》 《Git 學習小記之分支原理》

2. 經常使用的 git 命令?

git init                     // 新建 git 代碼庫
git add                      // 添加指定文件到暫存區
git rm                       // 刪除工作區文件,並且將這次刪除放入暫存區
git commit -m [message]      // 提交暫存區到倉庫區
git branch                   // 列出所有分支
git checkout -b [branch]     // 新建一個分支,並切換到該分支
git status                   // 顯示有變更的文件

詳細資料可以參考: 《常用 Git 命令清單》

3. git pull 和 git fetch 的區別

git fetch 只是將遠程倉庫的變化下載下來,並沒有和本地分支合併。

git pull 會將遠程倉庫的變化下載下來,並和當前分支合併。

《詳解 git pull 和 git fetch 的區別》

4. git rebase 和 git merge 的區別

git merge 和 git merge 都是用於分支合併,關鍵在 commit 記錄的處理上不同。

git merge 會新建一個新的 commit 對象,然後兩個分支以前的 commit 記錄都指向這個新 commit 記錄。這種方法會
保留之前每個分支的 commit 歷史。

git merge 會先找到兩個分支的第一個共同的 commit 祖先記錄,然後將提取當前分支這之後的所有 commit 記錄,然後
將這個 commit 記錄添加到目標分支的最新提交後面。經過這個合併後,兩個分支合併後的 commit 記錄就變爲了線性的記
錄了。

《git rebase 和 git merge 的區別》 《git merge 與 git rebase 的區別》


面試記錄總結

目錄

阿里巴巴(獲得 OFFER)

1. 2019-3-25 阿里巴巴(淘寶)一面

  1. 筆試題隨機排序
  2. 筆試題實現商品分配
  3. 瀏覽器存儲機制,cacheStorage
  4. cookie 原理
  5. 項目 mvp 原理
  6. Vue 組件間通信
  7. 雙向綁定的原理
  8. 網站性能優化
  9. 頁面的可用性時間的計算 performance api
  10. Webpack 配置
  11. Webassblem
  12. 網絡安全
  13. This的指向
  14. 前沿知識
  15. Hybrid
  16. Node.js
  17. 原型鏈
  18. 跨域
  19. 移動端的點擊事件
  20. 移動端佈局
  21. 前端路由的實現方式

面試時間:3.25 20:10-22:25 135分鐘

2. 2019-3-28 阿里巴巴(淘寶)二面

  1. 項目 mvp 模式
  2. 圖片優化
  3. 移動端開發基礎
  4. WebAssembly

3. 2019-4-1 阿里巴巴(淘寶)三面

  1. 項目介紹
  2. Vuex
  3. 項目 mvp 模式介紹
  4. Ajax請求創建
  5. Promise 調用
  6. Flex 佈局
  7. 盒模型
  8. Git rebase
  9. 隨機排序
  10. Promise
  11. Fetch 沒回答
  12. Grid 沒回答

面試時間: 4.1 15:20-15:57 37 分鐘

4. 2019-4-3 阿里巴巴(淘寶)四面(hr)

  1. 項目介紹
  2. 自我評價、同學評價
  3. 家鄉
  4. 自己的優點
  5. 學校課程
  6. 未來5年的規劃
  7. 投了哪些公司
  8. 學習生涯
  9. 有沒有女朋友
  10. 性格
  11. 從項目中學到的東西

面試時間: 4.3 16:20-16:47 27 分鐘

5. 2019-4-29 阿里巴巴(阿里雲)一面

  1. 快速排序
  2. 反轉鏈表
  3. 繼承
  4. 深度優先遍歷
  5. Es6
  6. 情景題 ui 組件設計
  7. 列表數據加載問題
  8. 懶加載擴展

6. 2019-5-27 阿里巴巴(阿里雲)二面

  1. Es6 新特性
  2. Object 方法
  3. Html5 方法
  4. Js 性能優化
  5. 快速排序不用遞歸實現

面試時間:5.27 20:32-20:58 26 分鐘

7. 2019-5-29 阿里巴巴(淘寶二輪)一面

  1. 簡歷第一個項目
  2. 簡歷第二個項目
  3. 簡歷第三個項目
  4. 服務端了解知識
  5. Node.js 瞭解
  6. 移動端相關
  7. React 基礎

面試時間:5.29 16:58-18:35 97分鐘

8. 2019-5-31 阿里巴巴(淘寶二輪)二面

  1. 項目經歷
  2. 技術選型
  3. 爲何這樣選擇
  4. 項目提效率提升亮點
  5. 項目目的

面試時間:5.31 12:58-13:20 22分鐘

9. 2019-5-31 阿里巴巴(淘寶二輪)三面(hr)

  1. 項目介紹
  2. 收穫
  3. 個人優勢
  4. 和騰訊offer 的選擇
  5. 職業規劃
  6. 如何獲取前端前沿知識

面試時間: 5.31 13:31-13:48 17分鐘

騰訊(獲得 OFFER)

1. 2019-4-26 騰訊(TEG)一面

  1. 實習時間
  2. 前端項目
  3. 節流與防抖
  4. margin 重疊
  5. BFC
  6. This 對象
  7. Loader 和 plugin 的差別
  8. 原型的獲取
  9. 單頁應用的seo
  10. EventBus
  11. Vuex

面試時間: 4.26 18:28-19:05 37分鐘

2. 2019-4-29 騰訊(TEG)二面

  1. 項目
  2. Vue router實現
  3. Vuex
  4. 項目管理規範
  5. 5個價值不同的問題分給5個不同的人的方式
  6. For of 和 for in 的區別
  7. 圖片加載
  8. 正則表達式
  9. 頁面遍歷
  10. 如何判斷參數是否傳入
  11. 路由如何保存滾動位置

面試時間:4.29 19:15-20:30 75 分鐘

3. 2019-5-9 騰訊(TEG)三面

  1. 項目經歷
  2. 最困難的事
  3. 興趣愛好
  4. 項目分工、人員討論
  5. 性格
  6. 面試是否會準備

面試時間: 5.9 19:03-19:43 40 分鐘

4. 2019-5-17 騰訊(TEG)四面(hr)

  1. 項目問題
  2. 新的解決方案
  3. 實驗室
  4. 最難的問題
  5. 家鄉
  6. 父母工作
  7. 對職位的看法
  8. 是否支持外地工作
  9. 是否有直系親屬在騰訊
  10. 實習時間
  11. 中間是否回校
  12. 興趣愛好
  13. 薪資有要求嗎

面試時間: 5.17 14:23-14:45 22分鐘

網易互娛(獲得 OFFER)

1. 2019-4-15 網易互娛一面

  1. 項目介紹
  2. Vue 理解
  3. 路由的理解
  4. ES6 理解

面試時間: 4.15 11:11-11:44 33 分鐘

2. 2019-4-18 網易互娛二面

  1. 項目介紹
  2. 權限系統的理解
  3. 對於爐石傳說的理解
  4. 代碼規範
  5. 商品利潤下降的原因

面試時間: 4.18 10:00-10:42 42 分鐘

字節跳動

1. 2019-3-23 字節跳動一面

  1. Webpack 瞭解
  2. http 緩存
  3. http1.0 和 http1.1 的區別
  4. css 上下固定爲100px,中間爲自適應高度
  5. 一道代碼分析題
  6. BFC
  7. 類數組有哪些,如何轉換
  8. 跨域
  9. cors 簡單請求和複雜請求的區別
  10. 項目中圖片的性能優化
  11. 前端的性能優化
  12. Base64 在 html 中的缺點
  13. 500 張圖片,如何實現預加載優化
  14. 二維碼掃描登錄的原理,服務器推送,客戶端輪詢

面試時間:3.23 9:00-10:17 67 分鐘

微衆銀行

1. 2019-4-1 微衆銀行一面

  1. Vue 雙向綁定
  2. 虛擬 Dom
  3. Diff 算法
  4. 閉包
  5. 閉包造成內存泄漏舉例
  6. 繼承
  7. http 和 https 的區別
  8. es6 的瞭解
  9. 是否會願意留在公司
  10. 你的優點
  11. 爲什麼選擇微衆

面試時間: 4.1 19:00-19:40 40 分鐘

酷家樂(獲得 OFFER)

1. 2019-4-18 酷家樂一面

  1. 基本數據類型
  2. null 和 undefined 的區別
  3. class 相對於 es5 的繼承有什麼區別
  4. 作用域和閉包
  5. Webpack loader 和 plugins 的區別
  6. 原型鏈和 this
  7. 輸入 url 的過程
  8. 層疊上下文
  9. Git rebase 和 git merge 的區別
  10. 前端學習的方式
  11. 爲什麼選擇前端

面試時間:4.18 14:35-15:10 35分鐘

2. 2019-4-22 酷家樂二面

  1. 項目介紹
  2. Vue 的雙向綁定機制
  3. 權限管理
  4. Vue 中組件通信方式
  5. Vue Data 中爲什麼要使用函數的方式
  6. 面向對象設計問題,自動超市購買商品設計
  7. 智力題,五隻雞五天能下五個蛋,多少隻雞一百天下一百個蛋
  8. 智力題,藥罐污染問題

面試時間: 4.22 15:06-16:06 60 分鐘

3. 2019-4-25 酷家樂三面

  1. 實習時間
  2. 前端方向
  3. 項目
  4. 懶加載
  5. 狀態持久化
  6. 圖片優化的方式
  7. 瀏覽器如何判斷是否支持 webp 格式圖片
  8. Display 的常見屬性
  9. 改變url的幾種方式

面試時間: 4.25 20:35-21:10 35分鐘

京東

1. 2019-4-22 京東一面

  1. 前端工程師的理解
  2. 項目介紹
  3. Vuex 的底層實現
  4. Vue router 的實現
  5. 緩存的瞭解
  6. Computed 和 watch 的區別
  7. Proto 和 ptototype
  8. Object.defineProperty() 方法
  9. 發佈訂閱者模式和觀察者模式的區別
  10. no-cache
  11. cache-control 可以有幾個值,沒有限制吧….
  12. webpack-loader
  13. 其他構建工具

面試時間: 4.22 11:01-10:32 31 分鐘

億聯網絡

1. 2019-4-24 億聯網絡一面

  1. 項目介紹
  2. 懶加載具體實現
  3. 數組打平
  4. Kmp
  5. 磁盤讀取
  6. 數據庫索引

面試時間:4.24 17:00-17:30 30分鐘

OPPO(獲得 OFFER)

1. 2019-4-26 OPPO一面

  1. Js 數據類型
  2. 判斷 Array
  3. DOMContentLoaded 事件和 Load 事件的區別
  4. 閉包
  5. 模塊化
  6. 模塊循環引用
  7. Js 文件異步加載
  8. Vue 雙向綁定
  9. Watch 和 computed
  10. 虛擬 dom
  11. 瀏覽器緩存

面試時間: 4.26 14:00-14:30 30分鐘

2. 2019-5-8 OPPO二面(hr)

  1. 自我介紹
  2. 壓力最大的時候
  3. 學習方法
  4. 爲什麼選擇 oppo
  5. 實習時間
  6. 其他的愛好
  7. 其他的公司

面試時間:5.8 16:30-16:50 20分鐘

華爲(獲得 OFFER)

1. 2019-4-28 華爲一面

  1. 項目經歷
  2. 實習時間

面試時間: 4.28 14:00-14:25 25分鐘

2. 2019-4-28 華爲二面

  1. 項目經歷
  2. 什麼是 es5
  3. Webpack
  4. 後端框架
  5. 有女朋友嗎
  6. 工作地點
  7. 實習時間

面試時間:4.28 14:30-14:55 25分鐘

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章