jsliang 的 2019 面試準備

jsliang發表於2019-03-17

Create by jsliang on 2019-2-11 15:30:34
Recently revised in 2019-3-17 21:30:36

Hello 小夥伴們,如果覺得本文還不錯,記得給個 star , 小夥伴們的 star 是我持續更新的動力!GitHub 地址

並不是只有特定的季節才能跑路,只因為人跑得多了,這條路就定下來了。

金三銀四跳槽季,jsliang2019年2月11日 寫下了這篇文章,開始準備自己的面試之旅。

2019年3月17日 為止,jsliang 搭建出個人的面試知識體系,海量地翻閱了一些前輩留下的資料,結合個人需求進行了幾場面試,從而進一步完善該文章並進行了發表,希望對準備跳槽或者正在跳槽中的小夥伴有所幫助。

一 目錄

不折騰的前端,和鹹魚有什麼區別

目錄
一 目錄
二 前言
2.1 自我介紹
2.2 跳槽原委
2.3 進擊目標
2.4 開篇點題
三 HTML
3.1 HTML 學習推薦
3.2 HTML 語義化
3.3 HTML5 新標籤
3.4 常見瀏覽器及其核心
3.5 cookies、session、sessionStorage、localStorage
四 CSS
4.1 CSS 學習推薦
4.2 CSS reset
4.3 CSS 盒模型
4.4 CSS 單位
4.5 CSS 選擇器
4.6 CSS 常見佈局
4.7 CSS3 新特性
4.8 BFC
4.9 行內元素和塊級元素
4.10 行內樣式、內嵌式、連結式以及匯入式
4.11 水平垂直居中
五 JavaScript
5.1 JS 學習推薦
5.2 JS 引用方式
5.3 原型與原型鏈
5.4 作用域與閉包
5.5 淺拷貝與深拷貝
5.6 模組化與元件化
5.7 物件導向與程式導向
5.8 防抖與節流
5.9 ES6
5.10 陣列操作
六 Vue
6.1 MVVM
6.2 生命週期
6.3 雙向資料繫結
6.4 Virtual DOM
6.5 template 編譯
6.6 key
6.7 nextTick
6.8 父子元件通訊
七 微信小程式
7.1 檔案主要目錄及檔案作用
7.2 微信小程式生命週期
7.3 如何封裝資料請求
7.4 頁面資料傳遞
7.5 載入效能優化的方法
7.6 微信小程式與原生 APP、Vue、H5 差異
7.7 微信小程式原理
八 瀏覽器
8.1 瀏覽器解析 URL
8.2 重繪與迴流
8.3 資料儲存
8.4 記憶體管理與垃圾回收
8.5 記憶體洩漏
九 網路協議
9.1 網路分層
9.2 HTTP/HTTPS
9.3 HTTP 狀態碼
9.4 TCP 三次握手與四次揮手
十 效能優化
10.1 HTML 優化
10.2 CSS 優化
10.3 JavaScript 優化
十一 演算法
十二 其他
十三 總結
十四 參考文獻
14.1 關於面試
14.2 關於 HTML
14.3 關於 CSS
14.4 關於 JS
14.5 關於其他
十五 網友反饋

二 前言

返回目錄

請時刻準備好自己的簡歷,不管是網際網路經濟不佳面臨裁員,還是因為公司內部鬥爭嚴重心亂如麻,還是因為厭倦了目前的一切……只有隨時更新自己,把自己的簡歷準備好,你才知道哪一刻跑路是最佳選擇。

2.1 自我介紹

返回目錄

Hello 小夥伴們好,我叫樑峻榮,網名叫 jsliang,由於崇拜前端大佬 技術胖jspang)的原因,又因為自己學的是前端(JavaScript),所以給自己取了個 jsliangJavaScriptLiang) 的網名,希望自己能通過建立自己的前端知識體系,從而在前端路上走得更遠。並將自己的經驗分享給小夥伴,攜手小夥伴們一起前行。

下面是講講個人故事:

首先jsliang 高考後的暑期就聽大學師兄的建議,開始學習程式設計,那時候學習了 C 語言,覺得世界上最神奇的事情不過如此,敲兩下鍵盤,按下回車,電腦就會一閃一閃地響應我們!於是在大學的時候,陸陸續續學過 C、C#、.Net 等……。

-_-|| 由於學得都是基礎,又都還給老師了,在這裡就不多累述了。

然後,在大二就開始接觸 HTML,那時候選修了個《網頁設計基礎》,跟著老師做了個只有幾個頁面的靜態網站。在大三的時候,參加了學校的特訓班,分角色按流程從頭到尾做了個包含角色管理、購物等功能的網站。同時,由於在特訓班的時候,看到後端使用 ThinkPHP(簡稱 TP),覺得蠻不錯的,於是自己搗鼓,使用 TP 3.2.3 + Bootstrap 3 + MySQL 打造了自己的部落格(已下線)。

接著,由於選修了門 Node.js 的課,所以也跟著大佬的步伐接觸了下 Vue、Koa 這些,那時候對 npm 等諸多不懂,為了折騰這個,我的前端世界自此開啟了個大門。

最後,我在自己的畢業設計中使用 Node.js + Vue + ElementUI + MongoDB 打造了個校園外賣、快遞代拿等功能的社群單頁應用。

在 2018 年 5 月的時候,家裡催促,於是直接出來面試。不像其他大佬的畢業等於失業,很幸運地 jsliang 面試第一家就給了 offer,於是就進了這家公司,那時候感覺自己前面的大學生活白過了,只懂 ES5、jQuery、HTML/HTML5、CSS/CSS3 的皮毛。

在熟悉了三個月的業務,公司給的任務能順利完成後,我覺得自己不夠努力:外面的前端翻天覆地,我的技術卻只是 jQuery is all!

於是 2018 年 8 月,jsliang 開始寫 Markdown,將 5 月份到 8 月份記錄到 Word 文件上的筆記整理成了 jsliang 的文件庫,並在 jsliang 的掘金 上發表了第一篇文章。

18 年 8 月至今,jsliang 大致經歷了以下這些:

  1. 學 Webpack,並用 Webpack 構建一個多頁面配置。然後幸運的是,剛好碰到公司的一個仿站任務,於是整個前端小組直接用了我的 Webpack + jQuery + VS Code 的 Live Share 套路進行協同開發!
  2. 學 微信小程式,並將它應用到電信開發的微信小程式專案翼小微中。
  3. 學 ECharts 報表,並用它做了個 Vue + ECharts 的報表,來展示愛音樂公司的運營資料。
  4. 學 Node,然後搭了個企業網站(company.jsliang.top),並寫了篇小文章(目前最高成就,獲得了 1100 多贊)。
  5. 學 Vue,由於之前學的 Vue,在工作上有好多沒有,逐漸淡忘了,所以從基礎開始,準備寫一套《Vue 從 0 到 1》。

以上,就是 jsliang 的程式設計生涯。

今兒,在這裡寫寫 jsliang 為了跳槽,根據個人想法進行的一些前端面試資料整理,小夥伴們覺得不錯的點個贊或者去 GitHub 點個 star,覺得有誤請指出,謝謝~

2.2 跳槽原委

返回目錄

馬老闆曾經說過,跳槽有兩個原因:

  1. 錢沒給到位。
  2. 心被委屈了。

首先,如果非要給 jsliang 我自己的跳槽定個位,那肯定是錢沒給到位,勞動與產出不成正比。在我 2018 年 5 月入職前,與人事的交談中瞭解到每年的 8 月和 2 月可以提薪,當初的技術棧是:HTML、CSS、ES5。

然後,2018 年 6 月到 2019 年 1 月,學習並應用到工作中的技術有:

  1. jQuery
  2. Webpack
  3. JSP
  4. 微信小程式
  5. Vue
  6. ECharts

其中 2018 年 8 月剛轉正,也不敢說自己技術進步很大,也不敢說自己專案貢獻很大,為公司謀了多大利益,所以沒有提薪想法。

2019 年 1 月底感覺自己專案也做了,凌晨 4/5/6 點的體育西路也看過了,技術也提升了,於是跟人事交談,期望 2 月能加薪,人事表示年終述職演講得好的給提薪,2 月開工的時候表示提薪名單沒我份……

你沒看錯,提薪全靠 PPT。PPT 裡提高了不給,沒提就是沒有。
當初想法很簡單,你隨便加個 5/600 我也滿足了。

最後jsliang 曾跟專案總監私下談話,建議可以發展一些新產品,這樣公司或許能獲取一些新收入,我也可以進一步挑戰我的技術。但是,由於我司是個老牌子公司,並且大部分依賴於接手電信專案進行擴張……

enm...所以心也委屈了。

在 2018 的努力下,GitHub 破 600 近 700 star,掘金破 10 萬閱讀量,3000 粉絲:
GitHub 見證:點選檢視
掘金見證:點選檢視

2.3 進擊目標

返回目錄

  • 目標城市:廣州
  • 目標薪資:10K - 15K
  • 目標技術:
1. 熟悉 HTML/HTML5、CSS/CSS3、ES5/ES6。
2. 瞭解 OOP 概念,並嘗試在工作中使用過 OOP 技巧。
3. 對 MVC/MVVM 架構有一定了解,如有 Vue/React/Angular 或者 微信小程式開發經驗更佳。
4. 使用過 Bootstrap 或者 ElementUI 等 UI 庫,並對前端 UI 庫有一定的個人理解。
5. 瞭解 Git、Webpack 等工具。
6. 對 Java、Node.js 等後端程式設計有一定了解。
7. 一年及以上工作經驗。
複製程式碼
  • 廣州前端分析:
  1. 廣州 13K 薪資要求:
    1. 2/3 年工作經驗。
    2. 熟悉 OOP,並能在工作中使用,且能獨立開發外掛等……
    3. 你可以不懂 Vue,但 React 你必須得會!
  2. 廣州 15k+ 薪資要求:
    1. 5 年+ 工作經驗。
    2. 全能,懂前端,熟悉後端,能寫文件……
    3. 帶領過小隊進行開發。
  3. 廣州異常偏科公司:
    1. 要求必須懂後端。
    2. 要求必須懂安卓或者 IOS 開發。
    3. 要求必須精通 jQuery 全家桶(jQuery UI、jQuery Mobile 等……)。

該分析資料來自 Boss 直聘

2.4 開篇點題

返回目錄

本文的知識點將涉及 HTML、CSS、JS、HTTP、Vue、Webpack、打包工具、效能優化等,沒有前置條件,看得懂可以瞅瞅複習下,看不懂可以瞅瞅學習下。

關於面試,在這記下慕課網視訊看到的,個人非常認同的三個問答:

  • 問:拿到一個面試題,第一時間看到什麼? 答:考點
  • 問:如何看待網上搜出來的永遠看不完的題海? 答:不變應萬變
  • 問:如何對待面試題? 答:題目到知識再到題目

然後在複習面試題的過程中,個人有些小看法:

  • 個人感言一:為什麼我總是比不上別人優秀?

當編寫業務程式碼中,碰到某個業務 bug 時,我會習慣性地百度這個業務 bug,看看網友是怎麼解決的。但是,學霸級的程式猿,會多走一步,他們會思考產生這個業務 bug 的底層原因是什麼,下次碰到類似的是如何應用該技術解決。所以,日積月累,我的確比不上人家了。

  • 個人感言二:辭職並不是件便捷的事。

way 1:面試成功,跟自己公司遞辭呈,走流程,同時跟對面 hr 申請一個月後入職。

way 2:面試成功,跟自己公司遞辭呈,詢問能不能快速離職,收到回覆跟對面 hr 確認時間。【推薦】

way 3:先遞辭呈,同時面試,面試成功的,一律申請走完原公司一個月的流程之後的日子入職。

jsliang 於 2 月底拿到 offer 並遞交辭呈,3 月 - 4 月進入一個月倒數計時,4 月第一週才能拿到離職證明。

最後在這裡祝各位小夥伴能找到稱心如意的工作~

三 HTML

返回目錄

HTML 屬於結構層,負責描繪出內容的結構。

CSS 屬於表示層,負責如何顯示有關內容。

JavaScript 屬於行為層,負責內容應如何對事件做出反應。

3.1 HTML 學習推薦

返回目錄

3.2 HTML 語義化

返回目錄

語義化的含義就是用正確的標籤做正確的事情,HTML 語義化就是讓頁面的內容結構化,它有如下優點:

  1. 便於對瀏覽器、搜尋引擎解析;
  2. 便於盲人瀏覽網頁;
  3. 便於閱讀原始碼的人對網站進行分開,維護和理解;

簡單來說,能用 <header><footer> 等 H5 新標籤的就不用 <div class="header">,不要使用 <div> 來存放段落等……

3.3 HTML5 新標籤

返回目錄

HTML5 中新增標籤大致有:<header><footer><aside><nav><video><audio><canvas>等等。

3.4 常見瀏覽器及其核心

返回目錄

Chrome Firefox Safari IE Opera
排版引擎 Blink Gecko Webkit Trident Blink
JS 引擎 V8 SpiderMonkey Nitro Chakra V8

國內一些瀏覽器使用較多的是 Webkit 核心。

  • 針對不同瀏覽器核心,HTML 辨別:
  1. IE 核心瀏覽器識別:<!--[if IE]><![endif]-->
  2. 非 IE 核心瀏覽器識別:<!--[if !IE]><![endif]-->
  • 針對不同瀏覽器核心,CSS 辨別:
/* 設定文字不可選取 */
* {
  -moz-user-select: none; /* 火狐 瀏覽器 */
  -webkit-user-select: none; /* Webkit 瀏覽器 */
  -o-user-select: none; /* Opera 瀏覽器 */
  -ms-user-select: none; /* IE10 瀏覽器 */
  -khtml-user-select: none; /* 早期瀏覽器 */
  user-select: none; /* 預設 */
}
複製程式碼

3.5 cookies、session、sessionStorage、localStorage

返回目錄

  • cookies:儲存於瀏覽器端的資料。可以設定 cookies 的到期時間,如果不設定時間,則在瀏覽器關閉視窗的時候會消失。

  • session:儲存於伺服器端的資料。session 儲存特定使用者會話所需的屬性和配置資訊。

  • cookiessession 的區別在於:

  1. cookies 資料存放在客戶的瀏覽器上,session 資料存放在伺服器上。
  2. 前端都是裸君子,沒有安全可言,cookies 可能會被黑客利用作資料欺騙。所以重要資訊記得存 session。
  3. session 如果在生效期內量過大,會佔用伺服器效能。
  4. 單個 cookies 儲存的資料不能超過 4 K,很多瀏覽器限制一個站點儲存最多 20 個 cookies。

  • sessionStorage:生命週期存在於標籤頁或視窗,用於本地儲存一個會話(session)中的資料,這些資料會隨著視窗或者標籤頁的關閉而被清空。

  • localStorage:生命週期是永久的,除非使用者主動清除瀏覽器上儲存的 localStorage 資訊,否則它將會永久存在。

  • sessionStoragelocalStorage 操作方法:setItemgetItem 以及 removeItem

以 localStorage 為例:

localStorage.getItem('name'); // 獲取 name 的值
localStorage.setItem('name', 'jsliang'); // 設定 name 的值為 jsliang
localStorage.removeItem('name'); // 刪除 name 的值
複製程式碼

參考 1:《前端分享之cookie的使用及單點登入》
參考 2:《Cookie、session和localStorage、以及sessionStorage之間的區別》

四 CSS

返回目錄

HTML 屬於結構層,負責描繪出內容的結構。

CSS 屬於表示層,負責如何顯示有關內容。

JavaScript 屬於行為層,負責內容應如何對事件做出反應。

4.1 CSS 學習推薦

返回目錄

4.2 CSS reset

返回目錄

在工作的過程中,會發現各式各樣的瀏覽器對某個標籤有自己獨特的樣式。

但是在前端開發中,如果不採用統一標準,那麼會產生千奇百怪的 bug。所以為了減少後期 bug 的出現,前端開發人員會重置一遍 CSS 樣式,儘可能地使開發的網頁在各個瀏覽器相差不大。

下面是 jsliang 在使用的樣式重置,當然如果小夥伴有不同的想法,可以去 百度/必應/google 搜尋並使用其他版本的樣式重置:

4.3 CSS 盒模型

返回目錄

在工作的過程中,也許小夥伴需要 div 塊的總寬度為 100px,然後發現總是被 margin 撐高,這是因為盒模型定義的問題:

CSS 中有個屬性叫 box-sizing

box-sizing: border-box
box-sizing: content-box
複製程式碼
  1. border-box 中,整個 div 的寬、高,包括 marginpaddingborder
  2. content-box 中,整個 div 的寬、高,則不包括上面元素。

jsliang 的 2019 面試準備

如上圖,如果一個 div ,你的程式碼如下:

div {
  box-sizing: border-box;
  margin: 10px;
  width: 100px;
  height: 100px;
  padding: 10px;
}
複製程式碼

那麼,你的整個寬高還是 100px

但是,如果你的程式碼如下:

div {
  box-sizing: content-box;
  margin: 10px;
  width: 100px;
  height: 100px;
  padding: 10px;
}
複製程式碼

那麼,你的整個盒子寬高是 120px

如果你在設計頁面中,發現內容區被撐爆了,那麼,請檢查下現在的 border-box 是什麼,最好在引用 reset.css 的時候,就對 border-box 進行統一設定,方便管理。

4.4 CSS 單位

返回目錄

在 CSS 中,除了我們常用的 px,還有其他單位小夥伴們可以瞭解一下:

單位 描述
% 百分比
px 畫素。計算機螢幕上的一個點為 1px
em 相對單位。相對於父元素計算,假如某個 p 元素為 font-size: 12px,在它內部有個 span 標籤,設定 font-size: 2em,那麼,這時候的 span 字型大小為:12 * 2 = 24px
rem 相對單位。相對於根元素 html 的 font-size,假如 html 為 font-size: 12px,那麼,在其當中的 div 設定為 font-size: 2rem,就是當中的 div 為 24px
rpx 微信小程式相對單位。1rpx = 螢幕寬度 / 750 px。在 750px 的設計稿上,1rpx = 1px。

除此之外還有 pt、ex 等單位,但由於不太好換算,故在此不提。

4.5 CSS 選擇器

返回目錄

選擇器是匹配元素的一種模式。

  • 關於 CSS 解析器:

HTML 經過解析生成 DOM Tree;而在 CSS 解析完畢後,需要將解析的結果與 DOM Tree 的內容一起進行分析建立一棵 Render Tree,最終用來進行繪圖。

Render Tree 中的元素與 DOM 元素相對應,但非一一對應:一個 DOM 元素可能會對應多個 renderer,如文字折行後,不同的「行」會成為 render tree 種不同的 renderer。也有的 DOM 元素被 Render Tree 完全無視,比如 display:none 的元素。

在建立 Render Tree 時,瀏覽器就要為每個 DOM Tree 中的元素根據 CSS 的解析結果來確定生成怎樣的 renderer。對於每個 DOM 元素,必須在所有 Style Rules 中找到符合的 selector 並將對應的規則進行合併。選擇器的「解析」實際是在這裡執行的,在遍歷 DOM Tree 時,從 Style Rules 中去尋找對應的 selector。

  • CSS 解析順序

在 CSS 的選擇器中,它會按照優先順序 從右向左解析,因為這樣匹配元素的時候,能儘量少地查詢,所以選擇器最好寫地簡潔一點。

  • CSS 常用選擇器
  1. 萬用字元:*
  2. ID 選擇器:#ID
  3. 類選擇器:.class
  4. 元素選擇器:pa 等……
  5. 後代選擇器:p spandiv a 等……
  6. 偽類選擇器:a:hover 等……
  7. 屬性選擇器:input[type="text"] 等……
  8. 子元素選擇器:li:firth-childp:nth-child(1) 等……
  • CSS 選擇器權重

!important -> 行內樣式 -> #id -> .class -> 元素和偽元素 -> * -> 繼承 -> 預設

4.6 CSS 常見佈局

返回目錄

  1. 水平垂直居中。這種佈局老生常談,jsliang 在本文也有提到,詳解請 點選連結
  2. 兩列布局。一側固定,另一側自適應。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Two Column Layout</title>
  <style>
    .container {
      display: flex;
    }
    .child-one {
      width: 300px;
      height: 300px;
      background: red;
    }
    .child-two {
      width: 100%;
      height: 300px;
      background: deepskyblue;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="child-one"></div>
    <div class="child-two"></div>
  </div>
</body>
</html>
複製程式碼
  1. 三列布局。類似於兩列布局,新增多一個固定寬的 <div> 塊而已。當然,小夥伴們可能會說:jsliang 你要考慮 flex 的相容性啊!enm...支援所有最新版本的瀏覽器!請更新你的瀏覽器哦親~

避免被寄刀片,附上 float 佈局:《css常見佈局》

4.7 CSS3 新特性

返回目錄

經典:CSS3 相關屬性你瞭解嗎,說說都有哪些?能說說你工作中常用的一些 CSS3 屬性嗎?

那麼,CSS3 新特性都有哪些呢?

  • transition:過渡
  • transform:旋轉、縮放、移動或者傾斜
  • animation:動畫
  • gradient:漸變
  • shadow:陰影
  • border-radius:圓角

為了方便記憶,我們將它們扔到同一個 HTML 檔案上,小夥伴拷貝到本地上開啟,可以看到一個擁有漸變的小球,做著橫向運動,如果你滑鼠移動到它上面,它的寬度會放大,並且進行傾斜。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"> 
<title>CSS3 新特性</title>
<style> 
  div {
    width: 100px;
    height: 100px;
    border-radius: 50px;
    background: linear-gradient(red, orange);
    box-shadow: 10px 10px 5px #888888;
    position: relative;
    transition: width 2s;
    animation: mymove 5s infinite;
  }
  div:hover {
    width:300px;
    transform: rotate(7deg);
  }
  @keyframes mymove {
    from { left: 0px; }
    to { left: 200px; }
  }
</style>
</head>
<body>
  <div></div>
</body>
</html>
複製程式碼

參考 1:《CSS3 圓角》
參考 2:《CSS3 漸變(Gradients)》
參考 3:《CSS3 transition 屬性》
參考 4:《CSS3 transform 屬性》
參考 5:《CSS3 animation(動畫) 屬性》
參考 6:《CSS3 box-shadow 屬性》
參考 7:《個人總結(css3新特性)》

4.8 BFC

返回目錄

  • 什麼是 BFC?

BFC 就是 塊級格式上下文,它是一個獨立的渲染區域,讓處於 BFC 內部的元素和外部的元素相互隔離,使內外元素的定位不會相互影響。

一定的 CSS 宣告可以生成 BFC,瀏覽器對生成的 BFC 有一系列的渲染規則,利用這些渲染規則可以達到一定的佈局效果。

  • 為什麼需要 BFC 呢?
  1. 它可以防止 margin 元素重疊(div 中包含 ul,而 div 與 ul 之間的垂直距離,取決於 div、ul、li 三者之間的最大外邊距,這時候給 ul 一個 display:inline-block 即可解決這個問題)
  2. 清除內部浮動(div 中包含 ul,而 ul 採用 float:left,那麼 div 將變成一長條,這時候給 div 加上規則使其變成 BFC 即可)
  • 如何產生 BFC?
  1. display: inline-block
  2. position: absolute/fixed
  • 工作中一般可能不會顧及這個:
  1. float 很少使用了,儘可能使用 flex
  2. css reset 一般會清除掉一些問題,減少 BFC 的使用。

參考文獻:《我對BFC的理解》

返回目錄

4.9 行內元素和塊級元素

返回目錄

行內元素:寬度和高度由內容決定,與其他元素共佔一行的元素,我們將其叫行內元素。例如:<span><i><a> 等……

塊級元素:預設寬度由父容器決定,預設高度由內容決定,獨佔一行並且可以設定寬高的元素,我們將其叫做塊級元素。例如:<p><div><ul> 等……

在日常開發中,我們經常使用 CSS 的 display 屬性來打破兩者的壁壘:display: inline-block,使它們擁有更多的狀態。

4.10 行內樣式、內嵌式、連結式以及匯入式

返回目錄

在引用 CSS 上,分為四種形式:行內樣式內嵌式連結式以及匯入式,下面介紹這四種模式。

  • 行內樣式

直接對 HTML 的標記使用 style 屬性,然後將 CSS 程式碼直接寫進去:

<p style="color: #fff; backgournd: deepskyblue;"></p>
複製程式碼
  • 內嵌式

將 CSS 寫 <head></head> 之間,並且用 <style></style> 標記進行宣告:

<head>
  <style>
    p {
      color: #fff;
      background: deepskyblue;
    }
  </style>
</head>
複製程式碼
  • 連結式

通過將 <style> 上的 CSS 提起到指定的 CSS 檔案上,然後通過 <link> 的方式在 HTML 上鍊接起來。

<head>
  <link href="reset.css" type="text/css" rel="stylesheet">
</head>
複製程式碼
  • 匯入樣式
<head>
  <style>
    @import url(reset.css);
  </style>
</head>
複製程式碼
  • 各種方式的優先順序

在優先順序上,行內樣式 > 連結式 > 內嵌式 > @import 匯入式

4.11 水平垂直居中

返回目錄

  • 什麼是 Flex 佈局?

Flex 是 Flexible Box 的縮寫,意為”彈性佈局”,用來為盒狀模型提供最大的靈活性。

  • Flex 佈局有哪些便利
/* 設定 Flex 模式 */
display: flex;

/* 決定元素是橫排還是豎著排,要不要倒序 */
flex-direction: column;

/* 決定元素換行格式,一行排不下的時候如何排 */
flex-wrap: wrap;

/* flex-flow = flex-direction + flex-wrap */
flex-flow: column wrap;

/* 同一排下對齊方式,空格如何隔開各個元素 */
justify-content: space-between;

/* 同一排下元素如何對齊,頂部對齊、中部對齊還是其他 */
align-items: center;

/* 多行對齊方式 */
align-content: space-between;
複製程式碼
  • 如何通過 Flex 實現元素水平垂直居中?

HTML

<div class="container">
  <div class="child"></div>
</div>
複製程式碼

CSS

.container {
  margin: 0 auto;
  width: 300px;
  height: 200px;
  background: deepskyblue;
  display: flex;
  /* 實現元素水平居中 */
  justify-content: center;
  /* 實現元素垂直居中 */
  align-items: center;
}
.child {
  width: 100px;
  height: 100px;
  background: #fff;
}
複製程式碼
  • 除了 Flex,還能使用其他形式進行水平垂直居中嗎?

HTML

<div class="container">
  <div class="child"></div>
</div>
複製程式碼

CSS

.container {
  position: relative;
  width: 300px;
  height: 200px;
  background: pink;
  margin: 0 auto;
}
.child {
  position: absolute;
  width: 100px;
  height: 100px;
  top: 50%;
  left: 50%;
  /* 下面兩種方式均可 */
  /* margin-top: -50px;
  margin-left: -50px; */
  transform: translate(-50%, -50%);
  background: #fff;
}
複製程式碼
  • 除此之外再談談 CSS 水平居中或者垂直居中?

水平居中:

  1. 行內元素:display: inline-block; text-align: center;
  2. 塊級元素:margin: 0 auto;
  3. Flex:display: flex; justify-content: center;

垂直居中:

  1. 行高 = 元素高:line-height: height
  2. Flex:display: flex; align-items: center;

參考文獻:
《CSS實現垂直居中的常用方法》
《CSS 用 position: absolute 與 transform 來居中塊級元素的問題》

五 JavaScript

返回目錄

HTML 屬於結構層,負責描繪出內容的結構。

CSS 屬於表示層,負責如何顯示有關內容。

JavaScript 屬於行為層,負責內容應如何對事件做出反應。

5.1 JS 學習推薦

返回目錄

  • 《JavaScript 高階程式(第三版)》
  • 《你不知道的 JavaScript》
  • 《JavaScript 忍者祕籍》
  • 《ES6 標準入門》—— 阮一峰
  • 《JavaScript 設計模式》—— 張容銘
  • 《JavaScript 設計模式與開發實踐》—— 曾探

5.2 JS 引用方式

返回目錄

  • 行內引入
<body>
  <input type="button" onclick="alert('行內引入')" value="按鈕"/>
  <button onclick="alert(123)">點選我</button>
</body>
複製程式碼
  • 內部引入
<script>
  window.onload = function() {
    alert("js 內部引入!");
  }
</script>
複製程式碼
  • 外部引入
<body>
  <div></div>

  <script type="text/javascript" src="./js/index.js"></script>
</body>
複製程式碼

注意

  1. 不推薦寫行內或者在 HTML 中插入 <script>,因為瀏覽器解析順序緣故,如果解析到死迴圈之類的 JS 程式碼,會卡住頁面。
  2. 建議在 onload 事件之後,即等 HTML、CSS 渲染完畢再執行程式碼。

5.3 原型與原型鏈

返回目錄

關於 prototype__proto__newcall()apply()bind()this 這些的知識點,由於篇幅太長,jsliang 已經抽離了出來,並做了簡潔詳細講解,詳見:

下面放出相關知識點:

jsliang 的 2019 面試準備

jsliang 的 2019 面試準備

  • 例項的 __proto__ 屬性(原型)等於其建構函式的 prototype 屬性。
  • Object.proto === Function.prototype
  • Function.prototype.proto === Object.prototype
  • Object.prototype.proto === null

5.4 作用域與閉包

返回目錄

在 JS 中,最容易混淆的就是作用域的情況。

在傳統的後端語言(例如 C 語言)中,一對花括號 {} 就是一個塊級作用域,作用域內變數不會相互影響,但是在 JS 中,像 if 條件語句的 {} 就不算一個獨立的作用域:

var x = 1;
console.log(x); // 1
if(true) {
  var x = 2;
  console.log(x); // 2
}
console.log(x); // 2
複製程式碼

所以有時候我們就需要變通,通過自執行函式建立臨時作用域:

function foo() {
  var x = 1;
  console.log(x); // 1
  if(x) {
    (function(x) {
      console.log(x); // 1
      var x = 2;
      console.log(x); // 2
    })(x)
  }
  console.log(x); // 1
}
foo();
複製程式碼

說到建立臨時作用域,我們就不得不談一下閉包。

那麼,什麼是閉包呢?

閉包簡單定義:函式 A 裡面包含了 函式 B,而 函式 B 裡面使用了 函式 A 的變數,那麼 函式 B 被稱為閉包。

又或者:閉包就是能夠讀取其他函式內部變數的函式

function A() {
  var a = 1;
  function B() {
    console.log(a);
  }
  return B();
}
複製程式碼
  • 閉包經典問題:現在我們有一段程式碼:
for(var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000);
}
複製程式碼

請問這段程式碼輸出什麼?

答案:3 個 3。
解析:首先,for 迴圈是同步程式碼,先執行三遍 for,i 變成了 3;然後,再執行非同步程式碼 setTimeout,這時候輸出的 i,只能是 3 個 3 了。

  • 那麼,我們有什麼辦法依次輸出 0 1 2 麼?
  1. 使用 let:
for(let i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000);
}
複製程式碼

在這裡,每個 let 和程式碼塊結合起來形成塊級作用域,當 setTimeout() 列印時,會尋找最近的塊級作用域中的 i,所以依次列印出 0 1 2。

如果這樣講不明白,我們可以執行下下面這段程式碼:

for(let i = 0; i < 3; i++) {
  console.log("定時器外部:" + i);
  setTimeout(function() {
    console.log(i);
  }, 1000);
}
複製程式碼

此時瀏覽器依次輸出的是:

定時器外部:0
定時器外部:1
定時器外部:2
0
1
2
複製程式碼

即程式碼還是先執行 for 迴圈,但是當 for 結束執行到了 setTimeout 的時候,它會做個標記,這樣到了 console.log(i) 中,i 就能找到這個塊中最近的變數定義。

  1. 使用立即執行函式解決閉包問題
for(let i = 0; i < 3; i++) {
  (function(i){
    setTimeout(function() {
      console.log(i);
    }, 1000);
  })(i)
}
複製程式碼

以上,我們就講解完了閉包及解決閉包的方式。

觀點 1:有些資料表示閉包中產生的大量區域性變數,會造成記憶體消耗過大,從而造成網頁的效能問題。
觀點 2:有些資料表示目前瀏覽器引擎都基於 V8,而 V8 引擎有個 gc 回收機制,不用太過擔心變數不會被回收。
提示:所以,如果你覺得不夠保險,那就在退出函式之前,將不使用的區域性變數全部刪除。

5.5 淺拷貝與深拷貝

返回目錄

  • 什麼是深拷貝?什麼是淺拷貝?

簡單來說,有兩個物件 A 和 B,B = A,當你修改 A 時,B 的值也跟著發生了變化,這時候就叫淺拷貝。如果不發生變化,就叫深拷貝。

  • 為什麼會出現深拷貝與淺拷貝?
  1. 首先我們需要知道基本資料型別(number、string、boolean、null、undefined)引用資料型別(無序物件,資料以及函式)
  2. 然後在基本資料型別中,例如:let a = 1; let b = a; a = 2; console.log(b)。當我們嘗試這樣子寫時,b 在棧記憶體中開闢了一個新記憶體,所以 b 的值不會改變,仍是 1.
  3. 接著在引用資料型別中,例如 let a = [1, 2, 3], b = a; a[0] = 3; console.log(b)。當我們嘗試這樣子寫時,b 會偷懶,引用跟 a 同一塊的記憶體地址,從而 a 的修改會影響 b,使得 b 變成 [3, 1, 3]。
  4. 最後,我們可以知道在引用資料型別中,會產生淺拷貝的問題。
  • 如何實現深拷貝?
  1. 首先我們嘗試使用遞迴去解決深拷貝:
function deepClone(obj) {
  let objClone = Array.isArray(obj) ? [] : {};
  if(obj && typeof obj === "object") {
    for(key in obj) {
      if(obj.hasOwnProperty(key)) {
        // 判斷 obj 子元素是否為物件,如果是,遞迴複製
        if(obj[key] && typeof obj[key] === "object") {
          objClone[key] = deepClone(obj[key]);
        } else {
          // 如果不是,簡單複製
          objClone[key] = obj[key];
        }
      }
    }
  }
  return objClone;
}

let a = [1, 2, 3, 4];
let b = deepClone(a);
a[0] = 2;
console.log(a, b);

// Console
// a = [2, 2, 3, 4];
// b = [1, 2, 3, 4];
複製程式碼
  1. 使用 JSON 物件的 parse 和 stringify

注意:採用 JSON 進行的深拷貝,無法拷貝到 undefined、function、symbol 這類資料,它是有小 bug 的深拷貝。

function deepClone(obj) {
 let _obj = JSON.stringify(obj);
 let objClone = JSON.parse(_obj);
 return objClone
}
let a = [0, 1, [2, 3], 4];
let b = deepClone(a);
a[0] = 1;
a[2][0] = 1;
console.log(a, b);

// Console
// a = [1, 1, [1, 3], 4];
// b = [0, 1, [2, 3], 4];
複製程式碼

5.6 模組化與元件化

返回目錄

在前端發展中,隨著前後端分離,前端社群的不斷壯大,前端能做的事情越來越多,承受的任務越來越重,程式碼也就越來越長了。就好比 jsliang 個人使用 jQuery 開發的時候,動不動就上千行程式碼,這在一個編輯器上看起來就有點亂了。如果碰上沒有程式碼摺疊的編輯器,你就更加難受了。

有的小夥伴的編輯器不是 VS Code,也不能進行程式碼摺疊

所以,面對越來越多的程式碼,我們就急需將這些程式碼分門別類,將程式碼按功能劃分,將同一功能的程式碼整合在一起,於是就有了模組化開發:一個檔案就是一個模組,當我們需要某個檔案的時候,我們只需要引用這個模組即可……

首先,是 CommonJS 的提出,在 Node.js 以及 Webpack 都支援 CommonJS,它規定了一個檔案就是一個模組,檔案內部定義的變數屬於這個模組,不會對外暴露從而汙染全域性變數的規則。在 CommonJS 中,通過 exports 或者 module.exports 進行匯出,通過 require 進行 同步載入 所需要依賴的模組。由於它是同步載入模組的形式,所以比較通用於伺服器端。

然後,根據 CommonJS 只能同步載入的問題,AMD 根據瀏覽器的特性,進行了非同步載入模組的提出。同時,AMD 有個問題,就是在使用 require.js 的時候,必須提前載入所有模組。

接著,根據 AMD 的問題,CMD 提出來了:通過按需載入的形式,哪裡需要就呼叫哪裡,而不用等到所有的模組都載入了再解析。

最後,ECMA 國際推出了 ES6 的 modules。在 ES6 中,通過 export 關鍵字匯出模組,通過 import 關鍵字引用程式碼。當然,由於瀏覽器廠商諸多,ES6 在瀏覽器的尚不支援,目前主流做法是先將 ES6 通過 babel 編譯成 require。

當然,JS 都進行模組化了,jsliang 想起自己專案中的那一坨 CSS,真心沒有回顧的想法!所以我們還需要知道為了方便管理 CSS,大佬們還是有做事兒的:Less 以及 Sass,這兩者使 CSS 的編寫更有組織性和目的性了。

說起模組化,我們又可以順帶提及元件化了,一開始為了區分這兩者,jsliang 也是百度了大量文章,最後成功把自己整蒙了,還是說說感覺可以的解釋:

元件化更關注的是 UI 部分:彈出框、頭部,內容區、按鈕等,都可以編寫成元件,然後在適用的地方進行引用。而模組化更側重於功能或者資料的封裝,比如全域性的 JSON 配置檔案,比如通用的驗證方法,比如規範時間戳等。

所以,說到這裡,我們就可以提到前端工程化:將整個開發流程就行工程規劃,從而提高整個團隊的開發效率。

在前端工程化中,最重要的就是提高整個團隊在 編碼 -> 測試 -> 維護 這三個階段的生產效率。團隊的協調至關重要,將每個任務細分給各個成員,從而獲取極致的工作效率,是管理者最喜歡看到的。而在上面的模組化和元件化的應用,就屬於前端工程化中的一部分,其目的就是在一些複雜的專案中,方便團隊進行合作開發,提高生產效率。

參考文獻:
《到底什麼是前端工程化、模組化、元件化》
《【前端工程化系列】簡談前端模組化開發與開發規範》
《個人關於模組化的理解》
《元件化開發和模組化開發概念辨析》
《JavaScript模組化 --- Commonjs、AMD、CMD、es6 modules》
《淺談什麼是前端工程化》

5.7 物件導向與程式導向

返回目錄

  1. 什麼是程式導向與物件導向?
  • 程式導向就是做圍牆的時候,由你本身操作,疊第一層的時候:放磚頭,糊水泥,放磚頭,糊水泥;然後第二層的時候,繼續放磚頭,糊水泥,放磚頭,糊水泥……
  • 物件導向就是做圍牆的時候,由他人幫你完成,將做第一層的做法抽取出來,就是放磚頭是第一個動作,糊水泥是第二個動作,然後給這兩個動作加上步數,最後告訴機器人有 n 層,交給機器人幫你工作就行了。
  1. 為什麼需要物件導向寫法?
  • 更方便
  • 可以複用,減少程式碼冗餘度
  • 高內聚低耦合

簡單來說,就是增加程式碼的可複用性,減少我們們的工作,使程式碼更加流暢。

  1. 手寫個物件導向程式碼?
function Person(name, phone) {
  this.name = name;
  this.phone = phone;
  this.eat = function() {
    console.log(name + " 吃飯");
  }

  return this;
}

let p1 = new Person("jsliang", "18818881888");
console.log(p1.name); // jsliang
p1.eat(); // jsliang 吃飯
複製程式碼

當然,jsliang 只能寫到這裡了,再寫下去就是設計模式等知識點了。

所以希望小夥伴們還是瞭解下物件導向思想,有助於進一步提升自己。

5.8 防抖與節流

返回目錄

關於 防抖與節流jsliang 特意將資料結合起來:

  • 防抖與節流
  • 重繪與迴流
  • 瀏覽器解析 URL
  • DNS 域名解析
  • TCP 三次握手與四次揮手
  • 瀏覽器渲染頁面

小夥伴們可以前往 《面試知識點 - JS 防抖與節流》 檢視。

5.9 ES6

返回目錄

ES6 是個大知識點,如果你面試的公司不是 “飽經滄桑” 的那種,那麼一定會出點 ES6 問題,例如:

  • 說說 let、var、const 區別
  • 講講 Promise 及其使用

因為 jsliang 感覺自己連 ES6 的門還沒進,所以在這裡就不 自作聰明,推薦下阮一峰大佬的教程:

希望小夥伴們看完能有所收穫,並在工作中大量使用。

5.10 陣列操作

返回目錄

在 JavaScript 中,用得較多的之一無疑是陣列操作,這裡過一遍陣列的一些用法:

  • map: 遍歷陣列,返回回撥返回值組成的新陣列
  • forEach: 無法break,可以用try/catch中throw new Error來停止
  • filter: 過濾
  • some: 有一項返回true,則整體為true
  • every: 有一項返回false,則整體為false
  • join: 通過指定連線符生成字串
  • push / pop: 末尾推入和彈出,改變原陣列, 返回推入/彈出項【有誤】
  • unshift / shift: 頭部推入和彈出,改變原陣列,返回操作項【有誤】
  • sort(fn) / reverse: 排序與反轉,改變原陣列
  • concat: 連線陣列,不影響原陣列, 淺拷貝
  • slice(start, end): 返回截斷後的新陣列,不改變原陣列
  • splice(start, number, value...): 返回刪除元素組成的陣列,value 為插入項,改變原陣列
  • indexOf / lastIndexOf(value, fromIndex): 查詢陣列項,返回對應的下標
  • reduce / reduceRight(fn(prev, cur), defaultPrev): 兩兩執行,prev 為上次化簡函式的return值,cur 為當前值(從第二項開始)

相信小夥伴在工作中耍的已經是一套一套的了,或者像 jsliang 一樣只會簡單的使用 pushmap 這幾個,感興趣的小夥伴可以 百度/bing/google 找找一些 奇技淫巧,說不定對工作效率有很大提升~

六 Vue

返回目錄

推薦:

  1. 技術胖
  2. 慕課網

6.1 MVVM

返回目錄

在 MVVM 架構下,View 和 Model 之間並沒有直接的聯絡,而是通過 ViewModel 進行互動,Model 和 ViewModel 之間的互動時雙向的,因此 View 資料會同步到 Model 中,而 Model 資料的變化也會立即反應到 View 上。

ViewModel 通過雙向資料繫結把 View 層和 Model 層連線了起來,而 View 和 Model 之間的同步工作完全是自動的,無需人為干涉,因此開發者只需要關注業務邏輯,不需要手動操作 DOM,不需要關注資料狀態的同步問題,複雜的資料狀態維護完全由 MVVM 來統一管理。

  1. M - Model。Model 代表資料模型,也可以在 Model 中定義資料修改和操作的業務邏輯。
  2. V - View。View 代表 UI 元件,它負責將資料模型轉化為 UI 展現出來。
  3. VM - ViewModel。ViewModel 監聽模型資料的改變和控制檢視行為、處理使用者互動,簡單理解就是一個同步 View 和 Model 的物件,連線 Model 和 View。

6.2 生命週期

返回目錄

  • 請大致講下 Vue 的生命週期?
  1. 建立前/後:在 beforeCreated 階段,Vue 例項的掛載元素 $el 和資料物件 data 以及事件還未初始化。在 created 階段,Vue 例項的資料物件 data 以及方法的運算有了,$el 還沒有。
  2. 載入前/後:在 beforeMount 階段,render 函式首次被呼叫,Vue 例項的 $el 和 data 都初始化了,但還是掛載在虛擬的 DOM 節點上。在 mounted 階段,Vue 例項掛載到實際的 DOM 操作完成,一般在該過程進行 Ajax 互動。
  3. 更新前/後:在資料更新之前呼叫,即發生在虛擬 DOM 重新渲染和打補丁之前,呼叫 beforeUpdate。在虛擬 DOM 重新渲染和打補丁之後,會觸發 updated 方法。
  4. 銷燬前/後:在執行例項銷燬之前呼叫 beforeDestory,此時例項仍然可以呼叫。在執行 destroy 方法後,對 data 的改變不會再觸發周期函式,說明此時 Vue 例項已經解除了事件監聽以及和 DOM 的繫結,但是 DOM 結構依然存在。
  • 什麼是 Vue 生命週期?

Vue 例項從建立到銷燬的過程,就是生命週期。從開始建立、初始化資料、編譯模板、掛載 DOM -> 渲染、更新 -> 渲染、銷燬等一系列過程,稱之為 Vue 的生命週期。

  • Vue 有幾個生命週期,它們的作用主要是什麼?

8 個,建立前/建立後、掛載前/掛載後、更新前/更新後、銷燬前/銷燬後。Vue 生命週期的作用是方便我們通過它的生命週期,在業務程式碼中更好地運算元據,實現相關功能。

  • 第一次頁面載入會觸發 Vue 哪幾個鉤子?

會觸發 4 個生命鉤子:建立前/建立後、掛載前/掛載後

  • DOM 渲染在哪個週期就已經完成?

beforeMounted 時它執行了 render 函式,對 $el 和 data 進行了初始化,但此時還是掛載到虛擬的 DOM 節點,然後它在 mounted 時就完成了 DOM 渲染,這時候我們一般還進行 Ajax 互動。

6.3 雙向資料繫結

返回目錄

Vue 採用 資料劫持 結合 釋出者-訂閱者 模式的方式,通過 Object.defineProperty() 來劫持各個屬性的 setter 以及 getter,在資料變動時釋出訊息給訂閱者,觸發相應的監聽回撥。

  1. 第一步:需要 Observe 的資料物件進行遞迴遍歷,包括子屬性物件的屬性,都加上 setter 和 getter。這樣的話,給這個物件的某個值賦值,就會觸發 setter,那麼就能監聽到了資料變化。
  2. 第二步:Compile 解析模板指令,將模板中的變數替換成資料,然後初始化渲染頁面檢視,並將每個指令對應的節點繫結更新函式,新增監聽資料的訂閱者,一旦資料有變動,收到通知,更新資料。
  3. 第三步:Watcher 訂閱者是 Observer 和 Compile 之間通訊的橋樑,主要做的事情有:
    1. 在自身例項化時往屬性訂閱器(dep)裡面新增自己。
    2. 自身必須有一個 update() 方法
    3. 待屬性變動 dep.notice() 通知時,能呼叫自身的 update() 方法,並觸發 Compile 中繫結的回撥,則功成身退。
  4. 第四步:MVVM 作為資料繫結的入口,整合 Observer、Compile 和 Watcher 三者,通過 Observer 來監聽自己的 model 資料變化,通過 Compile 來解析編譯模板指令,最終利用 Watcher 搭起 Observer 和 Compile 之間的橋樑,達到資料變化 -> 檢視更新;檢視互動變化(input) -> 資料 model 變更的雙向繫結效果。

js 實現簡單的雙向繫結

<body>
  <div id="app">
    <input type="text" id="txt">
    <p id="show"></p>
  </div>
  
  <script>
    window.onload = function() {
      let obj = {};
      Object.defineProperty(obj, "txt", {
        get: function() {
          return obj;
        },
        set: function(newValue) {
          document.getElementById("txt").value = newValue;
          document.getElementById("show").innerHTML  = newValue;
        }
      })
      document.addEventListener("keyup", function(e) {
        obj.txt = e.target.value;
      })
    }
  </script>
</body>
複製程式碼

Object.defineProperty 接收三個引數:物件,屬性名,配置物件
這裡使用的是 Object.defineProperty,這是 Vue 2.0 進行雙向資料繫結的寫法。在 Vue 3.0 中,它使用 Proxy 進行資料劫持。

  • 為什麼 Vue 3.0 中使用 Proxy 了?
  1. Vue 中使用 Object.defineProperty 進行雙向資料繫結時,告知使用者是可以監聽陣列的,但是隻是監聽了陣列的 push()、pop()、shift()、unshift()、splice()、sort()、reverse() 這八種方法,其他陣列的屬性檢測不到。
  2. Object.defineProperty 只能劫持物件的屬性,因此對每個物件的屬性進行遍歷時,如果屬性值也是物件需要深度遍歷,那麼就比較麻煩了,所以在比較 Proxy 能完整劫持物件的對比下,選擇 Proxy。
  3. 為什麼 Proxy 在 Vue 2.0 編寫的時候出來了,尤大卻沒有用上去?因為當時 es6 環境不夠成熟,相容性不好,尤其是這個屬性無法用 polyfill 來相容。(polyfill 是一個 js 庫,專門用來處理 js 的相容性問題-js 修補器)

參考自《實現雙向繫結Proxy比defineproperty優劣如何》

6.4 Virtual DOM

返回目錄

Vue 在 rendercreateElement 的時候,並不是產生真實的 DOM 元素,實際上 createElement 描述為 createNodeDescription,因為它所包含的資訊會告訴 Vue 頁面上需要渲染什麼樣的節點。

因此,我們將這樣的節點描述為 “虛擬節點”(Virtual Node),簡稱 VNode。“虛擬 DOM” 是我們對由 Vue 元件樹建立的整個 VNode 樹的稱呼。

作為一枚切圖仔,很榮幸地跟小夥伴說:“其實我也不懂 Virtual DOM!”

但是,總會有些面試場合會提到的,所以這裡找了幾篇資料,小夥伴們可以進一步學習:

其他的就需要小夥伴自己尋找了,如果覺得有不錯的解析 Virtual DOM 的文件/視訊,小夥伴也可以推薦過來哈~

6.5 template 編譯

返回目錄

  • Vue template 編譯的理解

Vue 中 template 就是先轉化成 AST 樹,再得到 render 函式返回 VNode(Vue 的虛擬 DOM 節點)。

  1. 通過 compile 編譯器把 template 編譯成 AST 語法樹(abstract syntax tree - 原始碼的抽象語法結構的樹狀表現形式),compile 是 createCompiler 的返回值,createCompiler 是用以建立編譯器的。另外 compile 還負責合併 option。
  2. AST 會經過 generate(將 AST 語法樹轉換成 render function 字串的過程)得到 render 函式,render 的返回值是 VNode,VNode 是 Vue 的虛擬 DOM 節點,裡面有標籤名、子節點、文字等待。

6.6 key

返回目錄

key 的作用就是在更新元件時判斷兩個節點是否相同。相同就複用,不相同就刪除舊的建立新的。

對於 diff 過程來說 key 是起不到提速作用的,詳見:key 的作用

6.7 nextTick

返回目錄

  • 用法:Vue.nextTick( [callback, context] )

  • 引數:

    • {Function} [callback]
    • {Object} [context]
  • 說明:在下次 DOM 更新迴圈結束之後執行延遲迴調。在修改資料之後立即使用這個方法,獲取更新後的 DOM。

  • 案例:

// 修改資料
vm.msg = 'Hello'
// DOM 還沒有更新
Vue.nextTick(function () {
  // DOM 更新了
})

// 作為一個 Promise 使用 (2.1.0 起新增,詳見接下來的提示)
Vue.nextTick().then(function () {
  // DOM 更新了
})
複製程式碼

關於 nextTick 的更多理解,jsliang 就不獻醜了,需要學習的小夥伴可以檢視:

或者自行查詢更優秀的資源。

6.8 父子元件通訊

返回目錄

關於 Vue 中的父子元件通訊,相信經常開發 Vue 的小夥伴比 jsliang 知道的多很多。

沒怎麼使用 Vue 的小夥伴可以看下下面的文章,並嘗試自己寫一寫:

下面我們講下使用 bus.js 實現非父子元件通訊:

假設在工作中,有三個 .vue 檔案:A.vue、B.vue、C.vue。A.vue 是主頁面,B.vue 和 C.vue 類似於頭部導航條和底部導航欄。現在,B.vue 點選會切換路由,C.vue 需要獲取 B.vue 傳遞的資訊。

A.vue

<template>
  <div>
    <top-nav></top-nav>
    <div class="container">
      <router-view></router-view>
    </div>
    <bottom-nav></bottom-nav>
  </div>
</template>
複製程式碼

bus.js

import Vue from 'vue';

// 使用 Event Bus
const bus = new Vue();

export default bus;
複製程式碼

B.vue

<template>
  <div class="bottom-nav">
    <div class="nav-one" @click="goToPage({path: '/HomeIndex', meta:'首頁'})">
      <i class="icon-home"></i>
      <span>首頁</span>
    </div>
  </div>
</template>

<script>
  import bus from '../utils/bus'
  export default {
    methods: {
      goToPage(route) {
        this.$router.push(route.path);
        bus.$emit('meta', route.meta);
      }
    }
  }
</script>
複製程式碼

C.vue

<template>
  <div class="top-nav">
    <span class="title">{{title}}</span>
  </div>
</template>

<script>
  import bus from '../utils/bus'
  export default {
    data() {
      return {
        title: ''
      }
    },
    created() {
      bus.$on('meta', msg=> {
        this.title = msg;
      })
    }
  }
</script>
複製程式碼

七 微信小程式

返回目錄

微信小程式,簡稱小程式,英文名 Mini Program,是一種不需要下載安裝即可使用的應用,它實現了應用“觸手可及”的夢想,使用者掃一掃或搜一下即可開啟應用。

7.1 檔案主要目錄及檔案作用

返回目錄

- component —————————————————— 元件資料夾
  - navBar                  —— 底部元件
    - navBar.js             —— 底部元件的 JS 程式碼
    - navBar.json           —— 底部元件的配置檔案
    - navBar.wxml           —— 底部元件的 HTML 程式碼
    - navBar.wxss           —— 底部元件的 CSS 程式碼
- pages  ————————————————————— 頁面資料夾
  - index                   —— 首頁
    - index.js              —— 首頁的 JS 程式碼
    - index.json            —— 首頁的配置檔案
    - index.wxml            —— 首頁的 HTML 程式碼
    - index.wxss            —— 首頁的 CSS 程式碼
- public ————————————————————— 圖片資料夾
- utils —————————————————————— 工具資料夾
  - api.js                  —— 控制 API 的檔案
  - md5.js                  —— 工具 - MD5 加密檔案
  - timestamp.js            —— 工具 - 時間戳檔案
- app.json ——————————————————— 設定全域性的基礎資料等
- app.wxss ——————————————————— 公共樣式,可通過 import 匯入更多
- project.config.json ———————— 專案配置檔案
複製程式碼

7.2 微信小程式生命週期

返回目錄

  • onLoad():頁面載入時觸發。
  • onShow():頁面顯示/切入前臺時觸發。
  • onReady():頁面初次渲染完成時觸發。
  • onHide():頁面隱藏/切入後臺時觸發。
  • onUnload():頁面解除安裝時觸發。

jsliang 的 2019 面試準備

7.3 如何封裝資料請求

返回目錄

  1. 封裝介面:

專案/utils/api.js

// 將請求進行 Promise 封裝
const fetch = ({url, data}) => {

  // 列印介面請求的資訊
  console.log(`【step 1】API 介面:${url}`);
  console.log("【step 2】data 傳參:");
  console.log(data);

  // 返回 Promise
  return new Promise((resolve, reject) => {
    wx.request({
      url: getApp().globalData.api + url,
      data: data,
      success: res => {
        
        // 成功時的處理 
        if (res.data.code == 0) {
          console.log("【step 3】請求成功:");
          console.log(res.data);
          return resolve(res.data);
        } else {
          wx.showModal({
            title: '請求失敗',
            content: res.data.message,
            showCancel: false
          });
        }

      },
      fail: err => {
        // 失敗時的處理
        console.log(err);
        return reject(err);
      }
    })
  })

}

/**
 * code 換取 openId
 * @data {
 *   jsCode - wx.login() 返回的 code
 * }
 */
export const wxLogin = data => {
  return fetch({
    url: "tbcUser/getWechatOpenId",
    data: data
  })
}
複製程式碼
  1. 呼叫介面:

專案/pages/login/login.js

import {
  wxLogin,
} from '../../utils/api.js'
複製程式碼
  1. 使用介面:

專案/pages/login/login.js

wxLogin({
  jsCode: this.data.code
}).then(
  res => {
    console.log("【step 4】返回成功處理:");
    console.log(res.data);
  },
  err => {
    console.log("【step 4】返回失敗處理:");
    console.log(err);
  }
)
複製程式碼

7.4 頁面資料傳遞

返回目錄

  1. 通過 url 攜帶引數,在 onLoad() 中通過 options 獲取 url 上的引數:

程式碼演示

<navigator url="../index/index?userId={{userId}}"></navigator>

<!-- 這兩段是分別在 HTML 和 JS 中的程式碼 -->

onLoad: function(options) {
  console.log(options.userId);
}
複製程式碼
  1. 通過 Storage 來傳遞引數:
wx.setStorageSync('userId', 'jsliang');
wx.getStorageSync('userId');
複製程式碼
  1. WXML 傳遞資料到 JS

login.wxml

<text bindtap="clickText" data-labelId="{{userId}}">點選傳遞資料到 JS</text>
複製程式碼

login.js

clickText(e) {
  console.log(e.currentTarget.labelid)
}
複製程式碼
  1. 元件呼叫傳參

元件接收資料:component-tag-name

Component({
  properties: {
    // 這裡定義了innerText屬性,屬性值可以在元件使用時指定
    innerText: {
      type: String,
      value: 'default value',
    }
  }
})
複製程式碼

使用元件的頁面定義 json

{
  "usingComponents": {
    "component-tag-name": "../component/component"
  }
}
複製程式碼

使用元件的頁面 HTML 程式碼

<view>
  <!-- 以下是對一個自定義元件的引用 -->
  <component-tag-name inner-text="Some text"></component-tag-name>
</view>
複製程式碼
  1. 通過介面呼叫傳遞引數

7.5 載入效能優化的方法

返回目錄

  1. 通過 this.$preload() 預載入使用者可能點選的第二個頁面。
  2. 元件化頁面,出現兩次以上的部分都進行封裝成元件。
  3. 提取共用的 CSS 樣式。
  4. 優化圖片:TinyPNG

7.6 微信小程式與原生 APP、Vue、H5 差異

返回目錄

  • 微信小程式優劣勢:

優勢

  1. 無需下載
  2. 開啟速度較快
  3. 開發成本低於原生 APP

劣勢

  1. 限制多。頁面大小不能超過 1M,不能開啟超過 5 個層級的頁面。
  2. 樣式單一。小程式內部元件已經成宿,樣式不可以修改。
  3. 推廣面窄。跑不出微信,還不能跑入朋友圈。
  • 微信小程式 VS 原生 APP

微信小程式有著低開發成本、低獲客成本、無需下載的優勢。

  • 微信小程式 VS H5
  1. 依賴環境不同。一個能在多種手機瀏覽器執行。一個只能在微信中的非完整的瀏覽器。
  2. 開發成本不同。一個可能在各種瀏覽器出問題。一個只能在微信中執行。
  • 微信小程式 VS Vue

微信小程式看似就是閹割版的 Vue。

7.7 微信小程式原理

返回目錄

  1. 本質上就是一個單頁面應用,所有的頁面渲染和事件處理,都在一個頁面中進行。
  2. 架構為資料驅動的模式,UI 和資料分離,所有頁面的更新,都需要通過對資料的更改來實現。
  3. 微信小程式分為兩個部分:webview 和 appService。其中 webview 主要用來展示 UI,appServer 用來處理業務邏輯、資料及介面呼叫。它們在兩個程式中進行,通過系統層 JSBridge 實現通訊,實現 UI 的渲染、事件的處理。

八 瀏覽器

返回目錄

8.1 瀏覽器解析 URL

返回目錄

關於 瀏覽器解析 URLjsliang 特意將資料結合起來:

  • 防抖與節流
  • 重繪與迴流
  • 瀏覽器解析 URL
  • DNS 域名解析
  • TCP 三次握手與四次揮手
  • 瀏覽器渲染頁面

小夥伴們可以前往 《面試知識點 - JS 防抖與節流》 檢視。

8.2 重繪與迴流

返回目錄

關於 重繪與迴流jsliang 特意將資料結合起來:

  • 防抖與節流
  • 重繪與迴流
  • 瀏覽器解析 URL
  • DNS 域名解析
  • TCP 三次握手與四次揮手
  • 瀏覽器渲染頁面

小夥伴們可以前往 《面試知識點 - JS 防抖與節流》 檢視。

8.3 資料儲存

返回目錄

  1. 儲存於程式碼中,程式碼執行完畢釋放記憶體。
  2. 儲存於瀏覽器中,cookie 用於短期儲存使用者身份,登入狀態等較小的資訊;localStorage/sessionStorage 用於長期儲存資料,瀏覽器關閉不影響它們的記憶體,相比於 cookie,storage 能儲存較多;IndexedDB 是瀏覽器提供的接近於 NoSQL 的資料庫,允許儲存大量資料。
  3. 儲存於資料庫中。

8.4 記憶體管理與垃圾回收

返回目錄

V8 將記憶體分為兩類:新生代記憶體空間和老生代記憶體空間。

  • 新生代記憶體空間:主要用來存放存活時間較短的物件。
  • 老生代記憶體空間:主要用來存放存活時間較長的物件。

這兩者通過不同的演算法,對記憶體進行管理操作。

8.5 記憶體洩漏

返回目錄

  • 意外的全域性變數:無法被回收。

  • 定時器:未被正確關閉,導致所引用的外部變數無法被釋放。

  • 事件監聽:沒有正確銷燬(低版本瀏覽器可能出現)。

  • 閉包:會導致父級中的變數無法被釋放。

  • DOM 引用:DOM 被刪除時,記憶體中的引用未被正確清空。

  • 如何檢視記憶體變化情況?

使用 Chrome 的 Timeline(新版本 Performance)進行記憶體標記,視覺化檢視記憶體的變化情況,找出異常點。

九 網路協議

返回目錄

9.1 網路分層

返回目錄

目前網路分層可分為兩種:OSI 模型和 TCP/IP 模型。

  • OSI 模型
  1. 應用層(Application)
  2. 表示層(Presentation)
  3. 會話層(Session)
  4. 傳輸層(Transport)
  5. 網路層(Network)
  6. 資料鏈路層(Data Link)
  7. 物理層(Physical)
  • TCP/IP 模型
  1. 應用層(Application)
  2. 傳輸層(Host-to-Host Transport)
  3. 網際網路層(Internet)
  4. 網路介面層(Network Interface)

更多詳情可以檢視下面這篇文章,裡面講得非常詳細:

9.2 HTTP/HTTPS

返回目錄

  • HTTP:超文字傳輸協議(HTTP)是用於分散式,協作式和超媒體資訊系統的應用協議。它是Web上資料交換的基礎,是一種 client-server 協議,也就是說請求通常是由像瀏覽器這樣的接受方發起的。
  • HTTPS:HTTPS(全稱:Hypertext Transfer Protocol over Secure Socket Layer),是以安全為目標的 HTTP 通道,簡單講是 HTTP 的安全版。即 HTTP 下加入 SSL 層,HTTPS 的安全基礎是 SSL,因此加密的詳細內容就需要 SSL。 它是一個 URI scheme(抽象識別符號體系),句法類同 http: 體系。用於安全的HTTP資料傳輸。https:URL 表明它使用了 HTTP,但 HTTPS 存在不同於 HTTP 的預設埠及一個加密/身份驗證層(在 HTTP 與 TCP 之間)。這個系統的最初研發由網景公司進行,提供了身份驗證與加密通訊方法,現在它被廣泛用於全球資訊網上安全敏感的通訊,例如交易支付方面。

9.3 HTTP 狀態碼

返回目錄

首先,我們大致區分下狀態碼:

  1. 1**開頭 - 資訊提示
  2. 2**開頭 - 請求成功
  3. 3**開頭 - 請求被重定向
  4. 4**開頭 - 請求錯誤
  5. 5**開頭 - 伺服器錯誤

然後,常見的狀態碼:

  1. 200 - 請求成功,Ajax 接受到資訊了。
  2. 400 - 伺服器不理解請求,工作中常見於跨域的時候後端給我報 400!
  3. 403 - 伺服器拒絕請求。
  4. 404 - 請求頁面錯誤。
  5. 500 - 伺服器內部錯誤,無法完成請求。

最後,小夥伴們如果想要了解更多,還是需要自行查詢資料的。

9.4 TCP 三次握手與四次揮手

返回目錄

關於 TCP 三次握手與四次揮手jsliang 特意將資料結合起來:

  • 防抖與節流
  • 重繪與迴流
  • 瀏覽器解析 URL
  • DNS 域名解析
  • TCP 三次握手與四次揮手
  • 瀏覽器渲染頁面

小夥伴們可以前往 《面試知識點 - JS 防抖與節流》 檢視。

十 效能優化

返回目錄

通過優化從而提高頁面的載入速度。

10.1 HTML 優化

返回目錄

  1. 避免 HTML 中書寫 CSS 程式碼,因為這樣難以維護。
  2. 使用 Viewport 加速頁面的渲染。
  3. 使用語義化標籤,減少 CSS 程式碼,增加可讀性和 SEO。
  4. 減少標籤的使用,DOM 解析是一個大量遍歷的過程,減少不必要的標籤,能降低遍歷的次數。
  5. 避免 src、href 等的值為空,因為即時它們為空,瀏覽器也會發起 HTTP 請求。
  6. 減少 DNS 查詢的次數。

10.2 CSS 優化

返回目錄

  1. 優化選擇器路徑:使用 .c {} 而不是 .a .b .c {}
  2. 選擇器合併:共同的屬性內容提起出來,壓縮空間和資源開銷。
  3. 精準樣式:使用 padding-left: 10px 而不是 padding: 0 0 0 10px
  4. 雪碧圖:將小的圖示合併到一張圖中,這樣所有的圖片只需要請求一次。
  5. 避免萬用字元:.a .b * {} 這樣的選擇器,根據從右到左的解析順序在解析過程中遇到萬用字元 * {} 會遍歷整個 DOM,效能大大損耗。
  6. 少用 float:float 在渲染時計算量比較大,可以使用 flex 佈局。
  7. 為 0 值去單位:增加相容性。
  8. 壓縮檔案大小,減少資源下載負擔。

10.3 JavaScript 優化

返回目錄

  1. 儘可能把 <script> 標籤放在 body 之後,避免 JS 的執行卡住 DOM 的渲染,最大程度保證頁面儘快地展示出來。
  2. 儘可能合併 JS 程式碼:提取公共方法,進行物件導向設計等……
  3. CSS 能做的事情,儘量不用 JS 來做,畢竟 JS 的解析執行比較粗暴,而 CSS 效率更高。
  4. 儘可能逐條操作 DOM,並預定好 CSs 樣式,從而減少 reflow 或者 repaint 的次數。
  5. 儘可能少地建立 DOM,而是在 HTML 和 CSS 中使用 display: none 來隱藏,按需顯示。
  6. 壓縮檔案大小,減少資源下載負擔。

十一 演算法

返回目錄

在演算法這塊,jsliang 覺得自己還是比較薄弱的,如果小夥伴們跟 jsliang 一樣,也想豐富下這方面知識,歡迎一起刷 LeetCode 共同進步:

十二 其他

返回目錄

在 【其他】 這章,原本 jsliang 想談談面試中的一些小技巧,例如談薪;或者講講 HR 面需要詢問的問題,例如工作時長、加班機制、調薪機制等……

但是,最終看來,jsliang 的經歷還是有所欠缺,所經歷的面試不夠 “盛大”,所以說出的話可能就是 “胡言亂語”、“誤導觀眾”,故在此就不獻醜了,如果小夥伴們想知道更多,可以通過 QQ 群:798961601 找到我。

☆ 目前 jsliang 通過 3 天的請假,去了 5 場面試,收穫了 3 份 offer。
☆ 如果小夥伴不知道簡歷該怎麼寫、面試總是鎮靜不下來、總感覺面試沒譜,可以先找 jsliang 聊聊,我會講講個人的面試經歷,以及聽到的其他小夥伴的經歷~

十三 總結

返回目錄

在觀看這篇文章的過程中,小夥伴可能會有這些疑問:

  1. 看完覺得不過癮啊!你怎麼就這麼 “短” 啊?

回答

系列套餐你值得擁有!

  1. 你這雜七雜八的都寫了什麼呀?看完我暈乎了!

回答

每個人的學習經歷是不同的,所擁有的技術、知識點以及工作經驗等都是不同的。

所以 jsliang 的目的是通過這篇文章充實自己的同時,順帶挖掘自己的不足,例如物件導向造輪子、演算法問題等讓 jsliang 想進一步折騰,並應用到工作中。

因此,小夥伴應該根據自己實際去擴充套件補充屬於自己的知識點。

畢竟瞭解自己的,只有自己!

  1. 好像你這裡寫得也不是很全啊?看完我還是一知半解的!

回答

每個人的目的都是不同的,不可能一篇文章寫完所有知識點,同時有些知識點可能 jsliang 也不感興趣、或者 jsliang 的層次不夠,接觸不到。

並且每個面試官都可能有自己的一套面試題,如果 jsliang 能將所有的面試題都寫出來,那還需要面試官做啥,大家都像考國家證照一樣直接電腦考試吧~(我也期待!!!)

如果小夥伴對文章存有疑問,想快速得到回覆。
或者小夥伴對 jsliang 個人的前端文件庫感興趣,也想將自己的前端知識整理出來。
或者小夥伴對文章後續的更新感興趣,掌握更多的面試技巧。
歡迎加 QQ 群一起探討:798961601

十四 參考文獻

返回目錄

本文中的許多內容,也許小夥伴看了會覺得眼熟,因為它們大部分是 jsliang 參考大量文獻,再經過刷選整理,最後根據自己理解後的一些闡述。

下面是個人覺得非常優秀的文章。

14.1 關於面試

返回目錄

  1. 《一位前端 2018 絕地求生記》
  2. 《中高階前端大廠面試祕籍,為你保駕護航金三銀四,直通大廠(上)》
  3. 《InterviewMap》
  4. 《一篇文章搞定前端面試》
  5. 《微信小程式必知面試題》
  6. 《微信小程式面試題,附答案》
  7. 《小程式踩過的那些面試題坑,附答案解決方法》

14.2 關於 HTML

返回目錄

  1. 《前端工程師手冊》
  2. 《HTML 教程- (HTML5 標準) - 菜鳥教程》
  3. 《前端分享之cookie的使用及單點登入》
  4. 《Cookie、session和localStorage、以及sessionStorage之間的區別》

14.3 關於 CSS

返回目錄

  1. 《前端工程師手冊》
  2. 《CSS 權威指南》
  3. 《CSS 揭祕》
  4. 《CSS 世界》
  5. 《我對BFC的理解》
  6. 《CSS實現垂直居中的常用方法》
  7. 《CSS 用 position: absolute 與 transform 來居中塊級元素的問題》
  8. 《css常見佈局》
  9. 《CSS3 圓角》
  10. 《CSS3 漸變(Gradients)》
  11. 《CSS3 transition 屬性》
  12. 《CSS3 transform 屬性》
  13. 《CSS3 animation(動畫) 屬性》
  14. 《CSS3 box-shadow 屬性》
  15. 《個人總結(css3新特性)》

14.4 關於 JS

返回目錄

  1. 【推薦】《JavaScript - MDN》
  2. 《小邵教你玩轉ES6》
  3. 《小邵教你玩轉JS物件導向》
  4. 《實現雙向繫結Proxy比defineproperty優劣如何》
  5. 《Vue 中關於 $emit 的用法》
  6. 《JavaScript 世界萬物誕生記》
  7. 《js中的new()到底做了些什麼??》
  8. 《MDN Function.prototype.call()》
  9. 《JavaScript中的call、apply、bind深入理解》
  10. 《箭頭函式 - 廖雪峰》
  11. 《ECMAScript 6 入門 - 阮一峰》
  12. 《Vue原理解析之Virtual Dom》
  13. 《virtual-dom(Vue實現)簡析》
  14. 《Vue.nextTick 的原理和用途》

14.5 關於其他

返回目錄

  1. 《前端效能優化最佳實踐》
  2. 《到底什麼是前端工程化、模組化、元件化》
  3. 《【前端工程化系列】簡談前端模組化開發與開發規範》
  4. 《個人關於模組化的理解》
  5. 《元件化開發和模組化開發概念辨析》
  6. 《JavaScript模組化 --- Commonjs、AMD、CMD、es6 modules》
  7. 《淺談什麼是前端工程化》
  8. 《前端分享之cookie的使用及單點登入》
  9. 《Cookie、session和localStorage、以及sessionStorage之間的區別》
  10. 《網路分層TCP/IP 與HTTP》

十五 網友反饋

返回目錄

檢視了下掘金評論區,感謝各位大大的反饋,由於本人將於 2019年4月1日 入職,故將一些個人覺得不錯的自己沒有察覺的知識點記錄下來,區分於原文,更為了猴年馬月後的下一次跳槽進一步完善。

意思就是,jsliang 這貨懶得改原文了,小夥伴們看著這裡進行知識點補充

  • 閉包定義

函式 A 裡面包含了 函式 B,而 函式 B 裡面使用了 函式 A 的變數,函式 B 被 return 了出去,那麼 函式 B 被稱為閉包。

  • box-sizing 屬性

當值為 border-box 時,寬度 width = content + padding + border,包含內邊距與邊框。

當值為 content-box 時,寬度 width = content,不包含內邊距與邊框。

  • em

em 是一個相對的大小,這裡的相對於元素父元素的 font-size

  • Side Project

Side Project 對應的中文就是副業、業餘專案或者小專案。

感興趣的小夥伴可以去了解一下。

  • pushshift 系列

這裡原文已備註是有誤的,只是一時沒空,沒有修改。

  • CSS 選擇器載入順序

原文:!important -> 行內樣式 -> #id -> .class -> 元素和偽元素 -> * -> 繼承 -> 預設

網友:“應該是最後的優先順序最高。”

這裡最後的優先順序最高應該是指同等級優先順序覆蓋。瀏覽器通過 CSSParser 將 CSS 解析成 CSS Rule Tree 的時候,沒錯的話應該是按照原文中的排序先載入,然後同等級的時候,後面的屬性覆蓋前面的屬性。

  • ARIA

對於 HTML5 的語義化,ARIA 的意思是 Accessible Rich Internet Application,aria-* 的作用就是描述這個 Tag 在視覺化的情境中的具體資訊。例如:

  1. aria-label:為元件指定內建的文字標籤,用來替代開發者沒有使用 <label> 標籤
  2. aria-labelledby:會讀取與此具有相同的 id 名的值

詳情可參考張鑫旭的 《WAI-ARIA無障礙網頁應用屬性完全展示》

  • sessionStorage 和 localStorage

文章描述不夠詳細。

  • 兩列布局/三列布局
  1. child-tow 中設定 width: 100% 的時候 child-one 的寬度會隨機而變,設定 flex: 1 就不會。所以看個人需求進行設定。
  2. 文章中沒有講到應對相容性怎麼設定,可以考慮使用 float 進行相關的佈局。
  • 淺拷貝與深拷貝

可參考文章:《深拷貝的終極探索(90%的人不知道)》

  • Promiseasync/await

文章描述不夠詳細。

  • 跨域

本來打算寫的,後面沒時間,給我刪了這塊,評論區有篇文獻參考:

《九種跨域方式實現原理(完整版)》

以上,即為目前評論區的補充,感謝各位小夥伴的點贊支援。


jsliang 廣告推送:
也許小夥伴想了解下雲伺服器
或者小夥伴想買一臺雲伺服器
或者小夥伴需要續費雲伺服器
歡迎點選 雲伺服器推廣 檢視!

jsliang 的 2019 面試準備
jsliang 的 2019 面試準備

知識共享許可協議
jsliang 的文件庫樑峻榮 採用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議進行許可。
基於github.com/LiangJunron…上的作品創作。
本許可協議授權之外的使用許可權可以從 creativecommons.org/licenses/by… 處獲得。

相關文章