前端面試

HTML

HTML語義化標籤

HTML5新增的語義化標籤有:header、nav、main、article、aside、footer等等javascript

 

HTML語義化就是讓頁面內容結構化,他有如下優勢:css

  1. 易於用戶閱讀,當用戶因網絡緣由沒法加載css或js時,可以讓頁面呈現清晰的結構。
  2. 有利於SEO搜索引擎的抓捕。
  3. 方便其餘設備解析,好比盲人閱讀器根據語義化標籤渲染網頁。
  4. 有利於開發維護,語義化更具可讀性,代碼更好維護。

HTML5新標籤

HTML5新增的標籤有:header、nav、video、audio、canvas、aside等等。html

HTML5新增了哪些內容

廣義上的HTML5指的是最新一代前端開發技術的總稱,包括:HTML五、CSS三、新增的webStorage等webAPI。前端

 

HTML中新增了header、footer、nav等語義化標籤,還新增了video、audio媒體標籤,新增了canvas畫布,還有一些標籤的新屬性,好比:input標籤的placeholder屬性。vue

 

CSS中新增了圓角、陰影、濾鏡、vw和vh長度單位,flex佈局,媒體查詢,過分和動畫,僞類等。java

 

js中新增了webStorage瀏覽器緩存策略、querySelector、webSocket、requestAnimationFrame、Worker線程、地理位置等。webpack

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

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

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

多個瀏覽器標籤頁之間的通訊

瀏覽器標籤頁之間是沒辦法直接通訊的,通常都是經過找一箇中介者來實現通訊。es6

  1. 使用websocket,通訊的標籤頁鏈接同一個服務器,發送消息到服務器後,服務器推送消息給全部鏈接的客戶端。
  2. 能夠適當的調用localStorage,localStorage在另外一個瀏覽上下文裏被添加、修改或刪除時,都會觸發一個storage事件,能夠經過監聽storage事件,控制它的值來進行頁面信息通訊。
  3. 若是能夠獲取對應標籤的引用,可經過postMessage方法向另外一個標籤頁傳遞數據。

H5中cookie的原理

cookie就是HTML5提供的一種緩存方式,一個cookie就是存儲在用戶主機瀏覽器中的一小段文本文件。Cookies是純文本形式,他們不包含任何可執行代碼。每一個cookie至關於一個用戶標識,在該頁面發送請求時,會攜帶對應頁面存儲的cookie值發送給後端用來判斷登陸狀態是否失效。

 

cookie還能夠用來存儲數據,可是瀏覽器供cookie存放數據的空間較少,若是須要存放大容量數據,推薦使用webStorage。

CSS

CSS盒模型

盒模型分爲標準盒模型和ie盒模型。標準盒模型爲content(內容)+padding(內邊距)+border(邊框)+margin(外邊距),而ie盒模型則爲content(內容)+padding(內邊距)+margin(外邊距)

 

標準盒模型和ie盒模型最根本的區別在於標準盒模型將邊框的單位長度算了進去,而ie盒模型沒有算進去,ie盒模型將邊框的單位長度算進內邊距中。

 

能夠經過box-sizing進行標準盒模型和ie盒模型之間的轉換。

標準盒模型:box-sizing: content-box;

ie盒模型:box-sizing: border-box;

rem和em的區別

rem和em都是css的長度單位,rem是相對於根元素html的font-size進行變化,em是根據父元素的fong-size進行變化的。

CSS選擇器

經常使用的選擇器

通配符選擇器:* ID選擇器:#ID 類選擇器:.class 元素選擇器:p、a、span等 後代選擇器:p span、div a等 僞類選擇器:a:hover、a:active等 屬性選擇器:input[type="text"]等

CSS選擇器權重

!import > 行內樣式 > #id > .class > 元素和僞元素 > * > 繼承 > 默認

CSS精靈圖

在CSS中,多個圖標集成到一張圖上使用background-position屬性設置的圖片,稱爲精靈圖(又稱圖片精靈)。

CSS新特性

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

元素性質:行內元素和塊級元素

行內元素(display: inline)

寬度和高度是由內容決定的,與其餘元素共佔一行不能設置寬高,例如:span標籤、a標籤、i標籤等等

塊級元素(display: block)

默認寬度由父容器決定,默認高度由內容決定,而且獨佔一行能夠設置寬高,例如:p標籤、div標籤、ul標籤等。

行內塊元素(display: inline-block)

寬度和高度由內容決定,與其餘元素共佔一行可是能夠設置寬高等,例如:img標籤等。

絕對定位和相對定位

position:absolute;

絕對定位,是相對於元素最近的已定位的父元素,若是沒有已定位的父元素,就相對於body元素進行定位。

 

position:relative;

相對定位,是相對於元素在文檔中的初始位置進行定位。

flex佈局

經過display:flex使該元素的子元素脫離文檔流,進行一些其餘的操做。

align-item: 定義元素橫向排列規則

flex-direction:  定義元素縱向排列規則

justify-content: 定義在主軸上的對齊方式

BFC

BFC格式化上下文,就是創做一個獨立的渲染區域,讓處於BFC內部的元素和外部相互隔離,使內外元素不受影響。

 

如何產生BFC

最有效的一種方式就是將元素的性質改變爲行內塊元素(display:inline-block),還能夠經過position:absolute/relative進行產生bfc。

最不推薦的一種方式就是給元素添加邊框,可是這種方式相比而言最簡單。

BFC的做用

  1. 上外邊距重疊,也就是margin塌陷問題
  2. 浮動引發的高度坍塌
  3. 文字環繞圖片問題,左邊圖片右邊文字。

水平垂直居中

經過flex佈局或者line-height屬性和text-align屬性進行佈置

less、sass和stylus的區別

  1. sass和less語法嚴謹,stylus相對自由。由於less長得更像css,因此它學習起來更容易。
  2. sass和stylus都具備類語言的邏輯方式處理:條件、循環等,而less須要經過when等關鍵字模擬這些功能,這方面less比不上sass和stylus。
  3. less在豐富性以及特點上都不及sass和stylus,

link和@import的區別

  1. link的功能比較多,能夠定義RSS,定義REL等做用,而@import只能用於加載css。
  2. 當瀏覽器解析到link標籤時,頁面會同步加載所引用的css,而@Import所引用的css會等到頁面加載完才被加載。
  3. @Import須要IE5以上才能使用,link沒有這個限制。
  4. link可使用js動態引入,@import不行。

多行元素的文本省略號

overflow : hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; // 控制行數 -webkit-box-orient: vertical

重繪和迴流(Repaint & Reflow)

根據瀏覽器渲染機制(下方瀏覽器部分中有解釋)能夠得知HTML被解析解析成了DOM,CSS被解析成了CSSOM,它倆合併產生了渲染樹Render Tree。

重繪

因爲節點的集合屬性發生改變或者因爲樣式改變而不會影響佈局的,稱爲重繪。例如outlinevisibilitycolorbackground-color等等,重繪的代價是高昂的,所以瀏覽器必須驗證DOM樹上其餘元素的可見性。

迴流

迴流是佈局或幾何屬性發生改變就稱爲迴流。迴流是影響瀏覽器性能的關鍵因素,由於其變涉及到部分頁面(或是整個頁面)的佈局更新。一個元素的迴流可能會致使其素有子元素以及DOM中緊隨其後的節點、祖先節點元素隨後的迴流。大部分的迴流將致使頁面的從新渲染。

 

迴流一定會發生重繪,重繪不必定會引起迴流。

JavaScript

JS的幾條基本規範

  1. 不要再同一行聲明多個變量
  2. 使用===/!==來比較true/false或者數值
  3. 使用字面量對象替代new Array這種形式
  4. 儘可能不要使用全局變量
  5. Switch語句必須帶有default分支
  6. 函數不該該有時候有返回值,有時候沒有返回值
  7. for循環必須使用大括號
  8. if語句必須使用大括號
  9. forin循環中的變量,應該使用let關鍵字聲明肯定做用域,從而避免做用域污染。

JS引入方法

行內引入

直接在標籤的方法中執行js語句。

內部引入

在script標籤中編寫js代碼,並執行

外部引入

經過script的src屬性指向一個js文件的路徑進行引入使用

JS的基本數據類型

string、number、boolean、undefined、null、symbol六種基本數據類型。

數組操做

循環

map函數、forEach函數、for循環、forin循環、forof循環。

過濾

filter函數

查找

對於一些簡單函數能夠直接使用in關鍵字查找,返回值爲boolean。

let p = [1, 2, 3]; console.log(1 in p) // true

includes函數:查找匹配項,若是有返回true,沒有返回false。

indexOf函數:正序查找匹配數據,返回下標。

lastIndexOf函數:倒敘查找匹配數據,返回下標。

some函數:有匹配項返回true時,總體爲true。

every函數:有匹配項返回false時,總體爲false。

添加

push函數:在數組的末尾添加一條數據。

unshift函數:在數組的開頭添加一條數據。

刪除

pop函數:在數組的末尾刪除一條數據。

shift函數:在數組的開頭刪除一條數據。

slice(start, end)函數:根據參數截取數組,並返回一個新數組,不會影響原來的數組。

splice(start, end, value....)函數:根據參數刪除數據並替換數據,返回當前操做後的數組,會影響原來的數組。

排序

sort函數:根據回調函數的具體邏輯將數組進行排列順序。

reverse函數:將數組按照如今的數據順序進行反轉。

其餘

concat函數:合併兩個數組。

reduce函數:在回調函數中對數組的每一條數據進行操做。

JS內置對象

Object是JavaScript中全部對象的父對象。

數據封裝對象:Object、Array、Boolean、Number和String。

其餘對象:Function、Arguments、Math、Date、Error、RegExp等。

閉包

一個函數中包含了另外一個函數,其中的函數使用到了第一個函數的變量,那麼其中的函數就叫作閉包。

閉包就是可以讀取其餘函數內部變量的函數。

 

特徵:

  1. 函數內部再嵌套一個函數。
  2. 內部函數能夠引用外層的參數和變量。
  3. 參數和變量不會被垃圾回收機制回收。

閉包的理解

使用閉包主要是爲了設計私有的方法和變量。閉包的優勢是能夠避免全局變量的污染,缺點shi閉包會常駐內存,增大內存使用量,容易形成內存泄漏。在js中,函數即閉包,只有函數纔會產生做用域的概念。

 

閉包最大的好處有兩個,一個是能夠讀取函數內部的變量,另外一個就是讓這些變量始終保持在內存中。

js中的同步和異步

由於JavaScript是單線程編程語言,因此同步和異步並非主線程執行同步代碼,再開一個線程執行異步代碼,而是經過消息隊列和事件循環的方式來進行同步和異步的劃分。

 

當js執行同步代碼時,一個任務執行完纔會去執行下一個任務,若是前一個任務耗時很長,那麼後一個任務不得不一直等着,這樣就會堵塞代碼執行。

 

同步任務指的是,在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行下一個任務。

異步任務指的是,不進入主線程、而進入消息隊列的任務,只有等主線程任務執行完畢,任務隊列開始通知主線程,請求執行任務,該任務纔會進入主線程執行。

異步運行機制

  1. 全部同步任務都在主線程上執行,造成一個執行棧。
  2. 主線程以外,還存在一個"消息隊列"。只要異步任務有告終果,就在"消息隊列"之中放置一個事件。
  3. 一旦"任務棧"中的全部同步任務執行完畢,系統就會讀取"消息隊列",看看裏面有哪些事件。那些對應的異步任務,因而結束等待狀態,進入執行棧,開始執行。
  4. 主線程不斷重複上面的第三步。

JavaScript的運行機制

簡單來講就是同步任務和異步任務的組合。

 

主線程先執行同步任務,當執行完畢同步任務時,去讀取"消息隊列",並執行消息隊列中的異步任務和其餘事件,而且一直重複這個過程(只要主線程中的同步任務爲空,就去讀取"消息隊列")。

 

注意:

"消息隊列"中除異步任務外,還有IO設備的事件以及一些用戶產生的事件(好比鼠標點擊、頁面滾動等等),這些相對耗時的操做。只要指定過這些事件的回調函數,這些事件發生時就會進入"消息隊列",等待主線程讀取。

JS做用域和做用域鏈

在js中做用域分爲全局做用域和局部做用域。

 

全局做用域能夠在程序的任何地方都能被訪問,好比window對象的內置屬性就具備全局做用域。

局部做用域只有在當前做用域內才能被訪問,不然會報錯"xxx is not defined"。

 

全局做用域能夠經過var關鍵字來聲明,也能夠在程序的最外部經過let關鍵字聲明。

局部做用域能夠在程序的某個代碼塊中經過let關鍵字聲明。

 

在使用變量的過程當中,會先在當前做用域查找是否認義了這個變量,若是找不到,就會向上級做用域去查,直到查到全局做用域,這個查找的過程叫作做用域鏈。

原型和原型鏈

在js中有一句話萬物皆對象,每一個對象都會在其內部初始化一個prototype屬性,這個屬性就是原型,當咱們訪問一個方法或者屬性的時候,若是這個對象內部不存在這個屬性,那麼他就會去prototype裏找這個屬性,這個prototype又有本身的prototype,這個樣一直找下去,直到找到Object內建對象,這個過程叫作原型鏈。

 

函數是一個另類,它具備兩個原型,一個prototype,一個proto。

高階函數

在javascript中,函數的參數能夠接收變量,因此一個函數做爲另外一個函數的參數的這種形式,稱爲高階函數。

 

 

組件和模塊化

當頁面代碼量過大,邏輯太多或者同一個功能組件在不少頁面均有使用,維護起來至關麻煩,這個時候,就須要組件化開發來進行功能拆分、組件封裝,達到組件通用性,加強代碼得可讀性,下降維護成本。

組件化開發的優勢

很大程度上下降系統各個功能得耦合性,而且提升了內部功能得聚合性。這對前端工程化及下降代碼得維護來講,是有很大的好處的,耦合性的下降,提升了系統的伸展性,下降了開發的複雜性,提高開發效率,下降開發成本。

 

  1. 專注:一個組件負責一個功能。
  2. 可配置性:可經過外部傳入數據進行組件內部的數據改變。
  3. 標準性:必須符和組件的特色(功能拆分、組件封裝、組件通用)。
  4. 複用性:能夠屢次使用。
  5. 可維護性:一個完整的組件,必須經過各個小組件來實現,若是後期出現問題能夠更快速的定位出現問題的組件。

模塊化

出現模塊化這個概念的緣由是由於早期版本的js沒有塊級做用域、沒有類、沒有包、也沒有模塊,這樣就帶來了複用、依賴、衝突、代碼組織混亂等一系列的問題,也就出現了模塊化這一律念。

模塊化的好處

  1. 避免變量衝突,命名污染。
  2. 提升代碼複用率。
  3. 提升了可維護性。
  4. 方便依賴關係管理。

模塊化的幾種方法

  1. 函數封裝。
  2. 當即執行函數表達式。

圖片的預加載和懶加載

  • 預加載:提早加載圖片,當用戶須要查看時可直接從本地緩存中渲染。
  • 懶加載:懶加載的主要目的是做爲服務器前端的優化,減小請求數或延遲請求書。

兩種技術的本質:二者的行爲是相反的,一個是提早加載,一個是遲緩甚至不加載。預加載會增長服務器前端壓力,懶加載對服務器有必定的緩解壓力。

mouseover和mouseenter的區別

mouseover:當鼠標移入元素或其子元素都會觸發事件,因此有一個重複觸發,冒泡的過程。對應的移除事件爲mouseout。

mouseenter:當鼠標移除元素自己(不包含子元素)會觸發事件,也就是不會冒泡,對應的移除事件是mouseleave。

解決異步回調地獄

經過promise、generator、async/await均可以解決。

對this對象的理解

this老是指向函數的直接調用者(並不是簡介調用者)。

 

若是有new關鍵字,this指向new出來的那個對象。

 

在事件中,this指向觸發這個事件的對象,特殊的是,IE中的attachEvent中的this老是指向全局對象Window。

VUE

Vue生命週期

Vue實例從建立到銷燬的過程,就是生命週期。也就是從開始建立、初始化數據、編譯模板、掛載DOM元素=>渲染、更新=>渲染、卸載等一系列過程,就是Vue的生命週期。

 

Vue的生命週期中有不少事件鉤子,能夠經過這些事件鉤子更好控制整個Vue實例的渲染和其中的各類邏輯。

 

Vue生命週期總共有幾個階段

總共有8個階段:

建立前(beforeCreate) => 建立後(created) => 載入前(beforeMount)=>載入後(mounted)=>更新前(beforeUpdate)=>更新後(updated)=>銷燬前(beforeDestroy)=>銷燬後(destroyed)

 

DOM元素渲染在mounted中就已經完成了。

每一個生命週期適合的場景

beforecreate : 能夠在這加個loading事件,在加載實例時觸發

created : 初始化完成時的事件寫在這裏,如在這結束loading事件,異步請求也適宜在這裏調用

mounted : 掛載元素,獲取到DOM節點

updated : 若是對數據統一處理,在這裏寫上相應函數

beforeDestroy : 能夠作一個確認中止事件的確認框

nextTick : 更新數據後當即操做dom

v-show和v-if的區別

v-show是經過切換元素的css屬性,v-if是dom的銷燬和從新建立。

使用頻繁切換時應該用v-show,使用較少時用v-if。

開發中經常使用的指令

v-html、v-model、v-bind、v-on、v-show、v-if、v-else-if、v-else等等。

動態化樣式屬性的方法

對象方法:v-bind:class="{'origin': isRipe, 'green': isNotRipe}"。

數組方法:v-bind:class="[class1, class2]"。

行內綁定:v-bind:style="{color: color, fontSize: fontSize + 'px'}"。

組件通訊

父組件向子組件傳值

在父組件中直接爲子組件綁定自定義屬性傳遞數據,子組件經過props接收。

 

父組件模板:

<template>  <Child :msg="message" /> </template>  <script> export default{  template: {  Child  },  data(){  return {  message: "向子組件傳遞的數據"  }  } } </script>

子組件模板:

<template>  {{ msg }} </template>  <script> export default{  props: { // 也可經過數組寫法,不進行類型檢查和參數限定  msg: {  type: String,  required: true  }  } } </script>

子組件向父組件傳遞數據

由於vue遵循單向數據流,在子組件中沒法直接向父組件傳遞數據,必須經過$emit()觸發父組件中的方法並將數據經過參數的方式傳遞過去。

 

父組件模板:

<template>  <Child @msgFunc="func" /> </template>  <script> export default{  template: {  Child  },  methods: {  func(msg){  console.log(msg); // 打印子組件傳遞過來的數據  }  } } </script>

子組件模板:

<template>  <button @click="handleClick()">觸發父組件的方法,並傳遞過去數據</button> </template>  <script> export default{  data(){  return {  message: "子組件的數據"  }  },  methods: {  handleClick(){  this.$emit("msgFunc", this.message); // 此處第二個參數有可能會不生效,推薦重定向下this指向。  }  } } </script>

兄弟組件之間傳值

兄弟組件之間傳值能夠經過Bus通訊,或者vuex完成。

 

實例化一個vue實例做爲Bus媒介,將該實例掛載到Vue原型鏈上方便調用,並經過$emit()和$on進行觸發方法和傳遞數據。

 

main.js文件:

import Vue from "vue";  let Bus = new Vue();  Vue.prototype.$Bus = Bus;  new Vue({...});

 

組件1:

<template>  {{ message }} </template>  <script> export default{  data(){  return {  message: ""  }  },  mounted(){  this.$Bus.$on("on", (msg) => { // 經過$on事件相應$emit事件  this.message = msg;  });  } } </script>

組件2:

<template>  <button @lick="toBus()">觸發on方法,並傳遞數據</button> </template>  <script> export default{  data(){  return {  msg: "兄弟組件中的數據"  }  },  methods: {  toBus(){  this.$Bus.$emit("on", this.msg);  }  } } </script>

Vue路由跳轉的方式

  1. 經過<router-link>標籤進行跳轉。
  2. 經過this.$router.push()函數式跳轉。

MVVM什麼意思

MVVM,按從左到右的順序,M表明Model數據模型,V表明View視圖,VM表明ViewModel視圖和數據的橋接器。

computed和watch有什麼區別

computed:

  1. computed是計算屬性,也就是計算值,它更多用於計算值的場景。
  2. computed具備緩存性,computed的值在getter執行後是會緩存的,只有在它依賴的屬性值改變以後,下一次獲取computed的值時纔會從新調用對應的getter來計算。
  3. computed適用於計算比較消耗瀏覽器性能的計算場景。

watch:

  1. 更多的是觀察的做用,在數據進行改變後執行的一些操做,相似於數據的監聽回調。
  2. 沒有緩存性,頁面從新渲染時值不發生變化也會執行。

 

當咱們須要進行數值計算,而且依賴於其餘數據時,就使用computed。若是隻是單純的監聽數據變化進行回調事件,那麼就使用watch。

Vue中的key有什麼做用

key是Vue中節點的惟一標識符,可使咱們的diff操做更準確、快速。

 

若是不加key,vue會選擇複用節點(Vue的就地更新策略),就會致使以前的節點的狀態被保留下來,使節點更新不許確,而且不利於被Map數據結構充分利用。

組件中的data爲何是一個函數

vue組件中data是一個函數並返回一個對象,而Vue實例中的data是一個對象。

 

這是由於在js中對象不具備做用域,而函數具備做用域。vue組件是用來複用的,必須是每一個組件的做用域相互隔離的,不會相互影響,而new Vue()實例是不會被複用,所以不存在引用對象問題。

nextTick()

在下一次DOM更新循環結束以後延遲執行回調。在修改數據以後,當即使用的這個回調函數,獲取更新後的DOM。

vm.smg = "數據"; // DOM還未更新 Vue.nextTick(() => {  // DOM更新 });

Vue插槽

vue中擁有具名插槽、匿名插槽和做用域插槽三種,三種插槽都是經過<slot>標籤進行分發內容,但做用域插槽是經過slot-scope屬性進行分發內容。

 

具名插槽擁有name屬性對父組件傳過來的數據進行匹配並分發內容。

vue-router導航守衛

在vue-router中能夠經過添加meta屬性對路由添加原信息進行路由權鑑,而且能夠在vue-router的路由鉤子中進行路由的重定向。

 

vue-router的路由鉤子有三種:

第一種:全局導航鉤子,router.beforeEach((to, from, next) = {}),在全局路由跳轉以前進行攔截。

第二種:組件內的鉤子。

第三種:單獨路由獨享鉤子。

vuex

vuex是vue的狀態管理組件,其中的state就是數據源存放地,對應通常vue對象裏面的data。

state中存放的數據是響應式的,vue組件從store讀取數據,如果store中的數據發生改變,依賴該數據的組件也會發生更新。

能夠經過mapState把全局的state和getters映射到當前組件的computed計算屬性。

 

vuex有5中屬性:分別是state、getter、mutation、action、module。

state

Vuex使用單一狀態樹,即每一個應用將僅僅包含一個store實例,但單一狀態樹和模塊化並不衝突。存放的數據狀態,不能夠直接修改裏面的數據。

mutation

在其中定義用於動態修改Vuex的store中的數據狀態的方法。

getter

至關於vue的計算屬性,主要用來過濾一些數據。

action

actions中定義的方法就是將mutation中的定義的處理數據的方法變成可異步的處理數據的方法,簡單的說就是異步操做數據。vue組件中經過store.dispatch()來分發action,也能夠經過mapAction將action中的方法映射進methods中。

 

vuex通常用於中大型web單頁應用中對應用的狀態進行管理,對於一些組件間關係較爲簡單的小型應用,使用vuex的必要性不是很大,由於徹底能夠用組件props屬性或者Bus事件來完成通訊,vuex更多地用於解決跨組件通訊以及做爲數據中心集中式存儲數據。

React

虛擬DOM

虛擬DOM至關於真實DOM的一個類對象,當應用的狀態發生改變時,會記錄新的虛擬DOM樹並於原先舊的虛擬DOM樹進行比較,再把其中發生的改變動新到真實DOM樹上。

 

虛擬DOM的優勢

  1. 保證性能下限:虛擬DOM能夠通過diff找到最小差別,而後批量進行patch,這種操做雖然比不上手動優化,可是比起粗暴的DOM操做性能要好不少,一次虛擬DOM能夠保證性能下限。
  2. 無需手動操做DOM:虛擬DOM的diff和patch都是在一次更新中自動進行的,開發者無需手動操做DOM,極大提升了開發效率。
  3. 跨平臺:虛擬DOM本質上是js對象,而DOM與平臺強相關,相比之下虛擬DOM能夠進行更方便的跨平臺操做,例如服務器渲染、移動端開發等等。

虛擬DOM的缺點

  • 沒法進行極致優化:在一些性能要求極高的應用中虛擬DOM沒法進行鍼對性的機制優化,好比VScode採用直接手動操做DOM的方式進行極端的性能優化。

React的生命週期

React 16以後有三個生命週期被廢棄,但沒有移除,因此仍是可使用,不過官方並不推薦這樣:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

目前React16.8+的生命週期分爲三個階段,分別是掛載階段、更新階段、卸載階段:

掛載階段

  • constructor: 構造函數,最早被執行,一般在構造函數中初始化state對象和爲自定義方法綁定this。
  • getDerivedStateFromProps: 若是咱們接收到新的屬性想去修改咱們的state,可使用此方法。
  • render:render函數是純函數,只返回須要渲染的東西,不該該包含其餘業務邏輯,能夠返回    原生的DOM、React組件、Fragment、Portals、字符串和數字、Boolean和null等內容。
  • componentDidMount:組件裝載以後調用,此時咱們能夠獲取到DOM節點並操做,好比對canvas和svg的操做,服務器請求,訂閱均可以寫在這裏,可是記得在componentWillUnmount中取消訂閱。

更新階段

  • getDerivedStateFromProps: 此方法在更新個掛載階段均可能會調用。
  • shouldComponentUpdate: shouldComponentUpdate(nextProps, nextState),有兩個參數nextProps和nextState,表示新的屬性和變化以後的state,返回一個布爾值,true表示會觸發從新渲染,false表示不會觸發從新渲染,默認返回true,咱們一般利用今生命週期來優化React程序性能。
  • render: 更新階段也會觸發今生命週期。
  • getSnapshotBeforeUpdate: getSnapshotBeforeUpdate(prevProps, prevState),這個方法在render以後,componentDidUpdate以前調用,有兩個參數prevProps和prevState,表示以前的屬性和以前的state,這個函數有一個返回值,會做爲第三個參數傳給componentDidUpdate,若是你不想要返回值,能夠返回null,今生命週期必須與componentDidUpdate搭配使用。
  • componentDidUpdate: componentDidUpdate(prevProps, prevState, snapshot),該方法在getSnapshotBeforeUpdate方法以後被調用,有三個參數prevProps,prevState,snapshot,表示以前的props,以前的state,和snapshot。第三個參數是getSnapshotBeforeUpdate返回的,若是觸發某些回調函數時須要用到 DOM 元素的狀態,則將對比或計算的過程遷移至 getSnapshotBeforeUpdate,而後在 componentDidUpdate 中統一觸發回調或更新狀態。

卸載階段

  • componentWillUnmount:當咱們的組件被卸載或者銷燬了久會調用,咱們能夠在這個函數裏去清除一些定時器,取消網絡請求,清理無效的DOM元素等垃圾清理工做。

React應用中的請求應該放在哪一個聲明週期中

若是將請求放在componentWillMount中能夠提早進行異步請求,避免白屏,可是當React渲染一個組件時,他不會等待componentWillMount完成任何事情,React會繼續執行render事件,沒有辦法暫停渲染以等待數據的到達。

 

並且在服務器渲染時,若是在componentWillMount中獲取數據,fetch data會執行兩次,一次在客戶端一次在服務端,這形成了多餘的請求,其次,在React 16進行React Fiber重寫後,componentWillMount可能在一次渲染中屢次調用。

 

官方推薦在componentDidMount中進行。若是有特殊需求須要提早請求,也能夠在constructor中請求。

setState是同步仍是異步的

setState有時會同步,有時會異步

  1. setState只在合成事件和鉤子函數中是異步的,在原生事件和setTimeout中都是同步的。
  2. setState的異步並非說內部由異步代碼實現,其實自己執行的過程和代碼都是同步的,只是合成事件和鉤子函數的調用順序在更新以前,致使在合成事件和鉤子函數中無法當即拿到更新後的值,造成了所謂的異步,固然能夠經過第二個參數setState(partialState, callback)中的callback拿到更新後的結果。
  3. setState 的批量更新優化也是創建在「異步」(合成事件、鉤子函數)之上的,在原生事件和setTimeout 中不會批量更新,在「異步」中若是對同一個值進行屢次setStatesetState的批量更新策略會對其進行覆蓋,取最後一次的執行,若是是同時setState多個不一樣的值,在更新時會對其進行合併批量更新。

React組件通訊

React中的組件通訊和Vue中組件通訊差很少,都分爲父子組件通信和其餘組件通信。

父子組件通信

  1. 父組件向子組件傳遞數據:父組件經過自定義屬性向子組件直接傳遞數據,子組件經過props接收。
  2. 子組件向父組件傳遞數據:父組件將自定義方法傳遞到子組件中,子組件經過props接收並傳遞函數參數調用。

其餘組件通信

  1. React中組件通信均可以經過Context進行數據傳遞,Context設計的目的是爲了共享那些對於一個組件樹而言是全局的數據。
  2. 發佈訂閱模式:發佈者發佈事件,訂閱者監聽事件並做出反應。咱們能夠經過引入event模塊進行通訊。
  3. 全局狀態管理:藉助Redux等全局狀態管理工具進行通訊,這種工具會維護一個全局狀態中心Store,並根據不一樣事件產生新的狀態。

ES6

var、let、const的區別

var聲明的變量不具備塊級做用域,而且能夠重複聲明變量,聲明後的變量會與window相映射,能夠在window對象中查找到,而且var聲明的變量具備變量提高,能夠先使用後聲明。

let聲明的變量具備塊級做用域,在同一個做用域內不能夠重複聲明名稱相同的變量,而且let聲明的變量不具備變量提高,必須先聲明後使用。

const聲明的是常量,一旦聲明賦值事後就沒法改變常量的值,而且支持塊級做用域。

解構賦值

能夠經過數組或對象的形式將數組或對象中的單個數據獲取出來。

// 對象解構 let {a, b} = {a: 1, b: 2};  // 數組解構 let [c, d, e] = [1, 2, 3];

還能夠將函數的參數經過對象解構的方式一一對應。

function personInfo({name, age, address, gender}){  console.log(arguments === {name, age, address, gender}); // true  console.log(name, age, address, gender); }  personInfo({gender: 'man', address: 'changsha', name: 'william', age: 18});

forEach、for in、for of的區別

forEach更多的是用來遍歷數組。

for in通常經常使用來遍歷對象或json

for of數組對象均可以遍歷,遍歷對象須要經過和Object.keys()配合

 

for in循環出來的是key,for of循環出的是value。

箭頭函數

箭頭函數又稱爲lambda表達式,是一種簡化函數定義的語法糖。

 

箭頭函數能夠省略參數那裏括號和包裹執行語句的大括號,表示直接返回執行語句。

let example = value => console.log(value);  

 

注意:

  1. 箭頭函數中的this不執行window對象,而是它的父級,就是誰調用它執行誰。
  2. 不能使用arguments對象獲取函數的參數。
  3. 不能用做構造函數,就是說不能使用new命令,不然會拋出一個錯誤。
  4. 不可使用yield命令,所以箭頭函數不能用做Generator函數。

Set和Map

Set用於數據重組,Map用於數據存儲。

Set

  1. 成員不能重複
  2. 只有值沒有鍵,相似數組
  3. 能夠遍歷,方法有add、delete、has

Map

  1. 本質上是鍵值對的集合,相似對象
  2. 能夠遍歷,能夠跟各類數據格式轉換。

Promise對象

Promise是一個構造函數,能夠經過new關鍵字聲明一個promise函數,它具備三種狀態,而且調用它其中一個狀態成功時就會凝固在這個狀態上,不發生改變。

 

在Promise函數中能夠經過then來調用它成功的狀態,catch調用它失敗的狀態,finaly調用執行結束的狀態。

let promise = new Promise((resolve, reject) => {  if(true){  resolve(...);  }else{  reject(...);  } }); promise.then((...) => {  ... }).catch((...) => {  ... });

 

AJAX相關

get請求傳參

HTTP協議並無規定GET/POST的請求長度限制,對get請求參數的限制是來源與瀏覽器或者web服務器,瀏覽器或者web服務器限制了url的長度,而且,有如下幾點:

  1. HTTP協議並未規定GET和POST的長度限制。
  2. GET的最大長度顯示是由於瀏覽器和web服務器限制了URL長度。
  3. 不一樣的瀏覽器和web服務器限制的最大長度不同。
  4. IE瀏覽器限制的最大長度大約爲2M,chrome瀏覽器限制的最大長度大約爲8M。

get請求和post請求的區別

  1. 最根本的區別在於傳遞數據的方式不一樣,get請求傳遞的數據會在url中顯示,而post請求會被放進虛擬載體中,用戶看不見傳遞的數據。
  2. get請求一般是獲取數據,而post請求是向後端傳遞數據並獲取必定的迴應。

同步和異步的區別

同步和異步最根本的區別在於,同步會阻塞代碼執行,可是異步不會。

 

同步至關於只有一條車道,一條車走完事後下一輛車再走,若是中間出現了問題,久會發生阻塞現象。

異步能夠理解爲有不少條通道,好幾輛車同時在不一樣的車道上行駛,並不會阻塞。

 

全部的ajax請求都是異步的。

 

ajax的優缺點

優勢

  1. 無刷新更新數據(在不刷新頁面的狀況下維持與服務器的通訊)
  2. 異步與服務器通訊(使用異步的方式與服務器進行通訊,不打斷用戶的操做)
  3. 前端和後端負載均衡(將一些後端的工做交給前端,減小服務器與後端的負擔)
  4. 界面和應用相分離(ajax將界面和應用分離也就是數據與呈現相分離)

缺點

  1. ajax不支持瀏覽器back按鈕
  2. 安全問題,ajax暴露了與服務器交互的細節
  3. 對搜索引擎的支持比較弱
  4. 破壞了back與history後退按鈕的正常行爲等瀏覽器機制

如何解決跨域問題

跨域的概念:協議、域名、端口都相同纔是同域,不然都是跨域。

 

  1. 使用jsonp技術,經過img標籤或script標籤天生支持跨域的場景請求後端數據。
  2. cors策略,讓後端配置後可跨域訪問。
  3. 配置代理,經過服務器的文件能訪問第三方資源。

瀏覽器相關

瀏覽器的渲染原理

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

渲染引擎並不會等到全部的HTML解析完成以後再去構建和佈局Render Tree,而是解析一部分就構建一部分,至關於熱更新同樣。

從瀏覽器地址欄輸入url到顯示頁面的步驟

  1. 瀏覽器根據請求的URL交給DNS域名解析,找到真實IP,向服務器發起請求。
  2. 服務器交給後臺處理完成後返回數據,瀏覽器接收文件(html、js、css、圖像等等)。
  3. 瀏覽器對加載到的資源(html、css、js等)進行語法解析,創建相應的內部數據結構(如htmlDOM)。
  4. 載入解析的資源文件,渲染頁面,完成。

webpack相關

webpack運行流程

分爲初始化、編譯、輸出三個階段.

初始化:

  1. 從配置文件和shell文件讀取、合併參數;
  2. 加載plugin
  3. 實例化compiler

編譯

  1. 從entry發出,針對每一個module串行調用對應loader翻譯文件內容
  2. 找到module依賴的module,遞歸進行編譯處理

輸出:

  1. 把編譯後module組合成chunk
  2. 把chunk轉換成文件,輸出到文件系統

webpack性能優化

優化能夠從兩個方面考慮,一個是優化開發體驗,一個是優化輸出質量。

優化開發體驗

  • 縮小文件搜索範圍。涉及到webpack如何處理導入文件,再也不贅述,不會的能夠自行搜索。因爲loader對文件轉換操做很耗時,應該儘可能減小loader處理的文件,可使用include命中須要處理的文件,縮小命中範圍。
  • 使用DllPlugin,提高構建速度
  • 使用happyPack開啓多線程
  • 使用UglifyJs壓縮代碼(只支持es5),uglifyes支持es6,兩個插件不能同時開啓。使用ParalellUgifyPlugin開啓多個子進程壓縮,既支持UglifyJs又支持uglifyes
  • 使用自動刷新:監聽到代碼改變後,自動編譯構建可運行代碼並刷新頁面
  • 開啓模塊熱替換:在不刷新網頁的同時實現實時預覽

優化輸出質量減小首屏加載時間

  • 區分環境
  • 壓縮代碼
  • CDN加速
  • 使用Tree shaking
  • 提取公共代碼
  • 按需加載

提高流暢度,即代碼性能:

  • 使用PrePack優化代碼運行時的效率
  • 開啓Scope Hoisting,讓webpack打包出來的代碼更小、運行更快

loader的原理

loader能把源文件翻譯成新的結果,一個文件能夠鏈式通過多個loader編譯。以處理scss文件爲例:

  • sass-loader把scss轉成css
  • css-loader找出css中的依賴,壓縮資源
  • style-loader把css轉換成腳本加載的JavaScript代碼

plugin原理

plugin用於擴展webpack功能。

  • webpack啓動後,在讀取配置時會先執行new BasicPlugin(options)初始化一個BasicPlugin得到它的實例
  • 調用BasicPlugin.apply(compiler)給插件實例傳遞compiler對象
  • 插件實例獲取compiler對象後,經過compiler.plugin(事件名,回調函數)監聽webpack廣播出的事例

 

http相關

url從輸入到輸出的過程1. 構建請求 構建請求行請求行包括請求方法請求http版本URI Get/Http/1.0 2. 查找強緩存 檢查強緩存命中則直接使用不然檢查協商緩存 3. DNS解析 域名與IP地址映射 4.創建tcp鏈接 chrome限制同一域名下最多6個tcp鏈接 + 經過三次握手創建鏈接 三次握手過程: 1.客戶端向服務器發送鏈接請求傳遞一個數據包syn此時客戶端處於SYN_SEND狀態 2.服務器接收syn報文後會以本身的syn報文做爲應答傳遞數據包syn+ack,此時服務器處於SYN-REVD狀態 3.客戶端接收syn報文後發送一個數據包ack此時客戶端處於ESTABLISHED狀態雙方已創建鏈接 + 進行數據傳輸 + 經過四次揮手斷開鏈接 四次揮手過程: 1. 客戶端發送一個FIN報文報文中指定一個序列號此時客戶端處於FIN_WAIT1狀態等待服務器確認 2. 服務器接收到FIN後會發送ACK確認報文代表已經收到客戶端報文此時服務端處於CLOSE_WAIT2狀態 3. 服務器發送FIN告訴客戶端想斷開鏈接此時服務端處於LAST_CHECK階段 4. 客戶端收到FIN後同樣發送一個ACK做爲應答此時客戶端處於TIME_WAIT階段須要過一段時間確認服務端收到本身的ACK報文 後纔會進入CLOSED狀態 5.發送http請求 6.網絡響應 7.瀏覽器解析和渲染 分爲構建dom樹樣式計算生成佈局樹8.生成佈局 觸發迴流和重繪 

介紹下半鏈接隊列

服務器第一次接收到客戶端的SYN後會處於SYN-REVD階段此時雙方尚未創建徹底的鏈接服務器會把此種狀態下請求鏈接放在一個隊列裏咱們把這種隊列稱爲半鏈接隊列 已經完成三次握手並創建鏈接就叫全鏈接隊列 

http和https區別

  1. http基於TCP/IP協議,https基於SSL/TLS協議
  2. http默認端口號爲80,https默認端口號爲443
  3. https安全性更強,須要CA證書
  4. https能夠防止運營商劫持
能夠介紹https的通訊過程,涉及對稱加密和非對稱加密

tcp和udp區別

  1. tcp只能一對一通訊,udp能夠一對1、一對多、多對多通訊,即支持多播和廣播
  2. tcp首部開銷消耗32字節,udp僅消耗8個字節
  3. tcp適合對數據安全性要求高的場景,好比文件傳輸,udp適合對數據實時性要求高的場景,好比視頻通話、語音通話
  4. tcp是有狀態鏈接,udp是無狀態的鏈接
  5. tcp-可靠傳輸 udp-不可靠傳輸
  6. tcp-面向字節流 udp-面向報文

tcp怎麼保證可靠性

1. 超時重傳機制 2. 對失序數據進行重排序 3. 應答機制 4. 滑動窗口 5. 擁塞控制 

http請求有哪幾種

http1.0:get、post、head

http1.1:put、delete、connect、trace、options

簡單請求:

  1. 請求method只能是get、post、head
  2. 請求頭只能是accept/accept-language/content-language/content-Type
  3. content-Type只能是text/plain、multipart/form-data、application/x-www-form-urlencoded

介紹http1.0|http1.1|http2.0

http1.0:

  1. 完成鏈接即斷開,致使從新慢啓動和三次握手
  2. 線頭阻塞,致使請求間相互影響

http1.1:

  1. 用keep-alive支持長鏈接
  2. 用host字段指定對應的虛擬站點
  3. 新增功能: 斷點續傳、身份認證、狀態管理、cache緩存->cache-control、expires、last-modified、etag

http2.0:

  1. 二進制分幀層:應用層和傳輸層
  2. header頭部壓縮
  3. 服務端推送
  4. 多路複用
二進制分幀層能夠擴展到計算機網絡的OSI參考模型

客戶端緩存

客戶端緩存分爲cookie、localStorage、sessionStorage、indexedDB,網上有關的文章不少,就不詳細說了

瀏覽器緩存

強緩存

不向http發送請求,返回狀態碼304.

檢查強緩存有兩個字段: http1.0使用expires,表明過時時間,可是服務器時間和客戶端時間可能不一致。爲了彌補這個缺點,http1.1使用cache-control的max-age字段,cache-control有多個指令

  • public 容許客戶端和代理服務器緩存
  • private 容許客戶端緩存
  • no-store 不使用緩存
  • no-cache 使用協商緩存 兩個字段都存在,cache-control優先級高於expires

協商緩存向http發送請求,返回狀態碼200

檢查協商緩存有兩個字段: http1.0使用last-modified,即最後修改時間。

  1. 在瀏覽器向服務器發送請求後,服務器會在響應頭上加上這個字段
  2. 瀏覽器接收後,若是再次請求,會在請求頭上攜帶If-Modified-Since
  3. 服務器拿到If-Modified-Since字段後,會和服務器中該資源的最後修改時間對比,若是請求頭中這個值小於最後修改時間,更新資源;不然返回304,告訴瀏覽器直接使用緩存

http1.1使用etag,etag是服務器根據當前文件內容,給文件生成的惟一標識,只要內容改變,這個值就會變。etag優先級高於last-modifed

緩存位置,按優先級從高到低分別是:

  • service worker
  • memory cache
  • disk cache
  • push cache

http狀態碼

列舉一些常見狀態碼便可

200-請求成功 301-永久重定向 302和307-臨時重定向 400-當前請求不能被服務器理解或請求參數有誤 401-請求須要認證或認證失敗 403-服務器禁止訪問 404-資源未找到 405-方法未容許 500-內部服務器錯誤 502-網關錯誤 503-服務器處於超負載或停機維護 

瞭解nginx嗎

ngnix是個高性能反向代理服務器,有如下做用:

  • 解決跨域
  • 請求過濾
  • 配置gzip
  • 負載均衡
  • 靜態資源服務器

ngnix解決跨域的原理:

  • 把後端域名設爲前端服務的域名,而後設置相應的location攔截前端須要跨域的請求,最後將請求代理回服務端的域名
  • ngnix實現負載均衡的策略:輪詢、最小連接數、最快響應時間

 

web安全

xss

跨站腳本攻擊,指攻擊者在網頁上注入惡意的客戶端代碼,經過惡意腳本對客戶端網頁進行篡改,從而在用戶瀏覽網頁時, 對客戶端瀏覽器進行控制或獲取用戶隱私數據的方式

防範:

  1. httpOnly防止截取cookie
  2. 用戶輸入檢查
  3. 用戶輸出檢查
  4. 利用CSP(瀏覽器的內容安全策略)

csrf

跨站請求僞造,劫持受信任用戶向服務器發送非預期請求的方式。

防範:

  1. 驗證碼
  2. referer check
  3. 增長token驗證

二次封裝axios

1.新建一個axios對象定義好字段並設置默認值好比超時時間請求頭 2.定義過濾字符串方法過濾服務端爲空字符串或null的屬性 3.請求攔截器調用過濾字符串方法遍歷url上的字段若是爲數組或對象轉爲JSON對象 4.響應攔截器捕獲錯誤根據http狀態碼進行不一樣的處理好比401跳轉登錄頁面403返回您沒有權限502返回系統正在升級中請稍後重試504返回系統超時並彈出對應的消息提示框消息提示框自定義 

axios調用流程

查看axios源碼axios調用流程實質是Axios.prototype.request的實現調用過程以下: 1.判斷傳入參數config是不是字符串是則設置url不然設置config爲對象 2.調用mergeConfig方法合併默認參數和用戶傳入的參數 3.若是設置了請求方法將其轉爲小寫不然設置請求方法爲get 4.將用戶設置的請求和響應攔截器發送請求的dispatchRequest組成promise鏈最後返回promise實例這一步保證先執行請求攔截器再執行請求最後執行響應攔截器
相關文章
相關標籤/搜索