整理了一張前端面試思惟導圖我放在了文章最後面,因爲圖片太大,建議下載查看。javascript
本文整理了面試大體思路以及一些基礎知識點,但願能給你帶去些許幫助,助力你找到心儀的好工做。css
注意點(克服緊張,語速放慢,目光直視面試官)html
面試官下午好,我叫**,今天來應聘貴公司的前端工程師崗位。我從事前端開發兩年多,有X年多的Vue開發經驗,一年React開發經驗,在上家公司主要從事H5頁面,後臺管理系統,混合App等項目開發。日常喜歡逛一些技術社區豐富本身的技術,像思否,掘金之類,而且本身也獨立開發了我的博客網站,記錄本身的工做總結和學習心得。 個人性格比較溫和,跟同事朋友相處時比較外向,在工做中代碼開發時我喜歡全心全意的投入,對於工做我總抱着認真負責的態度。面試官,以上是個人介紹,謝謝。前端
這部分大機率會問,注意語言措辭,作好充足的準備沒你就不會慌張,安全感是本身給本身的。 示例:vue
項目簡介:XXAPP是一款多功能的民營銀行軟件,主要有帳戶交易、轉帳匯款、存單產品買入賣出、充值提現等功能,使用原生內嵌webview的方式,通訊方面iOS採用messageHandlers[fn].postMessage(data)
方法。Android
採用window.AndroidWebView[fn] (data)
html5
項目亮點及難點:登陸超時從新登陸後繼續返回原先操做的頁面。java
語義化意味着顧名思義,HTML5的語義化指的是合理正確的使用語義化的標籤來建立頁面結構,如
header,footer,nav,從標籤上便可以直觀的知道這個標籤的做用,而不是濫用div。
語義化的優勢有:
代碼結構清晰,易於閱讀,利於開發和維護
方便其餘設備解析(如屏幕閱讀器)根據語義渲染網頁。
有利於搜索引擎優化(SEO),搜索引擎爬蟲會根據不一樣的標籤來賦予不一樣的權重
複製代碼
網頁生成過程:node
HTML
被HTML解析器解析成DOM
樹css
則被css解析器解析成CSSOM
樹DOM
樹和CSSOM
樹,生成一棵渲染樹(Render Tree
)flow
),即將全部渲染樹的全部節點進行平面合成paint
)在屏幕上重排(也稱迴流): 當DOM
的變化影響了元素的幾何信息(DOM
對象的位置和尺寸大小),瀏覽器須要從新計算元素的幾何屬性,將其安放在界面中的正確位置,這個過程叫作重排。 觸發:react
重繪: 當一個元素的外觀發生改變,但沒有改變佈局,從新把元素外觀繪製出來的過程,叫作重繪。 觸發:webpack
color、background、box-shadow
等屬性重排優化建議:
DOM
元素position:absolute
或fixed
元素,對其餘元素影響不大GPU
加速,translate
使用3D
變化transform
不重繪,不迴流 是由於transform
屬於合成屬性,對合成屬性進行transition/animate
動畫時,將會建立一個合成層。這使得動畫元素在一個獨立的層中進行渲染。當元素的內容沒有發生改變,就沒有必要進行重繪。瀏覽器會經過從新複合來建立動畫幀。
全部HTML
元素能夠看做盒子,在CSS中,"box model"
這一術語是用來設計和佈局時使用。 CSS
盒模型本質上是一個盒子,封裝周圍的HTML
元素,它包括:邊距,邊框,填充,和實際內容。 盒模型容許咱們在其它元素和周圍元素邊框之間的空間放置元素。
!important>style>id>class
BFC
是 Block Formatting Context
的縮寫,即塊格式化上下文。BFC
是CSS佈局的一個概念,是一個環境,裏面的元素不會影響外面的元素。 佈局規則:Box是CSS佈局的對象和基本單位,頁面是由若干個Box組成的。元素的類型和display屬性,決定了這個Box的類型。不一樣類型的Box會參與不一樣的Formatting Context
。 建立:浮動元素 display:inline-block position:absolute
應用: 1.分屬於不一樣的BFC
時,能夠防止margin
重疊 2.清除內部浮動 3.自適應多欄佈局
BOM(Browser Object Model)
是指瀏覽器對象模型,能夠對瀏覽器窗口進行訪問和操做。使用 BOM,開發者能夠移動窗口、改變狀態欄中的文本以及執行其餘與頁面內容不直接相關的動做。 使 JavaScript
有能力與瀏覽器"對話"。 DOM (Document Object Model)
是指文檔對象模型,經過它,能夠訪問HTML
文檔的全部元素。 DOM
是 W3C
(萬維網聯盟)的標準。DOM
定義了訪問 HTML
和 XML
文檔的標準: "W3C 文檔對象模型(DOM)是中立於平臺和語言的接口,它容許程序和腳本動態地訪問和更新文檔的內容、結構和樣式。" W3C DOM
標準被分爲 3 個不一樣的部分:
DOM
- 針對任何結構化文檔的標準模型XML DOM
- 針對 XML 文檔的標準模型HTML DOM
- 針對 HTML 文檔的標準模型什麼是 XML DOM
? XML DOM
定義了全部 XML 元素的對象和屬性,以及訪問它們的方法。 什麼是 HTML DOM? HTML DOM 定義了全部 HTML 元素的對象和屬性,以及訪問它們的方法。
string、number、boolean、null、undefined、object(function、array)、symbol(ES10 BigInt)
typeof
主要用來判斷數據類型 返回值有string、boolean、number、function、object、undefined。
instanceof
判斷該對象是誰的實例。null
表示空對象 undefined
表示已在做用域中聲明但未賦值的變量閉包是指有權訪問另外一個函數做用域中的變量的函數 ——《JavaScript高級程序設計》
當函數能夠記住並訪問所在的詞法做用域時,就產生了閉包,
即便函數是在當前詞法做用域以外執行 ——《你不知道的JavaScript》
原型: 對象中固有的__proto__
屬性,該屬性指向對象的prototype
原型屬性。
原型鏈: 當咱們訪問一個對象的屬性時,若是這個對象內部不存在這個屬性,那麼它就會去它的原型對象裏找這個屬性,這個原型對象又會有本身的原型,因而就這樣一直找下去,也就是原型鏈的概念。原型鏈的盡頭通常來講都是Object.prototype
因此這就是咱們新建的對象爲何可以使用toString()
等方法的緣由。
特色: JavaScript
對象是經過引用來傳遞的,咱們建立的每一個新對象實體中並無一份屬於本身的原型副本。當咱們修改原型時,與之相關的對象也會繼承這一改變。
this
對象是是執行上下文中的一個屬性,它指向最後一次調用這個方法的對象,在全局函數中,this
等於window
,而當函數被做爲某個對象調用時,this等於那個對象。 在實際開發中,this
的指向能夠經過四種調用模式來判斷。
this
指向全局對象。this
指向這個對象。this
指向這個用new
新建立的對象。apply 、 call 和 bind
調用模式,這三個方法均可以顯示的指定調用函數的 this 指向。apply
接收參數的是數組,call
接受參數列表,`` bind方法經過傳入一個對象,返回一個
this 綁定了傳入對象的新函數。這個函數的
this指向除了使用
new `時會被改變,其餘狀況下都不會改變。new
prototype
對象。this
指向這個對象,執行構造函數的代碼(爲這個新對象添加屬性)做用域
負責收集和維護由全部聲明的標識符(變量)組成的一系列查詢,並實施一套很是嚴格的規則,肯定當前執行的代碼對這些標識符的訪問權限。(全局做用域、函數做用域、塊級做用域)。 做用域鏈就是從當前做用域開始一層一層向上尋找某個變量,直到找到全局做用域仍是沒找到,就宣佈放棄。這種一層一層的關係,就是做用域鏈
。
(1)第一種是以原型鏈的方式來實現繼承
,可是這種實現方式存在的缺點是,在包含有引用類型的數據時,會被全部的實例對象所共享,容易形成修改的混亂。還有就是在建立子類型的時候不能向超類型傳遞參數。
(2)第二種方式是使用借用構造函數
的方式,這種方式是經過在子類型的函數中調用超類型的構造函數來實現的,這一種方法解決了不能向超類型傳遞參數的缺點,可是它存在的一個問題就是沒法實現函數方法的複用,而且超類型原型定義的方法子類型也沒有辦法訪問到。
(3)第三種方式是組合繼承
,組合繼承是將原型鏈和借用構造函數組合起來使用的一種方式。經過借用構造函數的方式來實現類型的屬性的繼承,經過將子類型的原型設置爲超類型的實例來實現方法的繼承。這種方式解決了上面的兩種模式單獨使用時的問題,可是因爲咱們是以超類型的實例來做爲子類型的原型,因此調用了兩次超類的構造函數,形成了子類型的原型中多了不少沒必要要的屬性。
(4)第四種方式是原型式繼承
,原型式繼承的主要思路就是基於已有的對象來建立新的對象,實現的原理是,向函數中傳入一個對象,而後返回一個以這個對象爲原型的對象。這種繼承的思路主要不是爲了實現創造一種新的類型,只是對某個對象實現一種簡單繼承,ES5 中定義的 Object.create() 方法就是原型式繼承的實現。缺點與原型鏈方式相同。
(5)第五種方式是寄生式繼承
,寄生式繼承的思路是建立一個用於封裝繼承過程的函數,經過傳入一個對象,而後複製一個對象的副本,而後對象進行擴展,最後返回這個對象。這個擴展的過程就能夠理解是一種繼承。這種繼承的優勢就是對一個簡單對象實現繼承,若是這個對象不是咱們的自定義類型時。缺點是沒有辦法實現函數的複用。
(6)第六種方式是寄生式組合繼承
,組合繼承的缺點就是使用超類型的實例作爲子類型的原型,致使添加了沒必要要的原型屬性。寄生式組合繼承的方式是使用超類型的原型的副原本做爲子類型的原型,這樣就避免了建立沒必要要的屬性。
JS
是單線程的,爲了防止一個函數執行時間過長阻塞後面的代碼,因此會先將同步代碼壓入執行棧中,依次執行,將異步代碼推入異步隊列,異步隊列又分爲宏任務隊列和微任務隊列,由於宏任務隊列的執行時間較長,因此微任務隊列要優先於宏任務隊列。微任務隊列的表明就是,Promise.then
,MutationObserver
,宏任務的話就是setImmediate setTimeout setInterval
ajax是一種異步通訊的方法,從服務端獲取數據,達到局部刷新頁面的效果。 過程:
XMLHttpRequest
對象;open
方法傳入三個參數 請求方式(GET/POST)、url、同步異步(true/false)
;onreadystatechange
事件,當readystate
等於4時返回responseText
;event.stopPropagation()
或者 ie下的方法 event.cancelBubble = true;
//阻止事件冒泡
${data}
);MVVM是Model-View-ViewModel
縮寫,也就是把MVC
中的Controller
演變成ViewModel。Model
層表明數據模型,View
表明UI組件,ViewModel
是View
和Model
層的橋樑,數據會綁定到viewModel
層並自動將數據渲染到頁面中,視圖變化的時候會通知viewModel
層更新數據。
每一個Vue
實例在建立時都會通過一系列的初始化過程,vue
的生命週期鉤子,就是說在達到某一階段或條件時去觸發的函數,目的就是爲了完成一些動做或者事件
create階段
:vue實例被建立 beforeCreate
: 建立前,此時data和methods中的數據都尚未初始化 created
: 建立完畢,data中有值,未掛載mount階段
: vue實例被掛載到真實DOM節點 beforeMount
:能夠發起服務端請求,去數據 mounted
: 此時能夠操做Domupdate階段
:當vue實例裏面的data數據變化時,觸發組件的從新渲染 beforeUpdate
updated
destroy階段
:vue實例被銷燬 beforeDestroy
:實例被銷燬前,此時能夠手動銷燬一些方法 destroyed
computed與watch
watch 屬性監聽 是一個對象,鍵是須要觀察的屬性,值是對應回調函數,主要用來監聽某些特定數據的變化,從而進行某些具體的業務邏輯操做,監聽屬性的變化,須要在數據變化時執行異步或開銷較大的操做時使用
computed 計算屬性 屬性的結果會被緩存,當computed
中的函數所依賴的屬性沒有發生改變的時候,那麼調用當前函數的時候結果會從緩存中讀取。除非依賴的響應式屬性變化時纔會從新計算,主要當作屬性來使用 computed
中的函數必須用return
返回最終的結果 computed
更高效,優先使用
使用場景 computed
:當一個屬性受多個屬性影響的時候使用,例:購物車商品結算功能 watch
:當一條數據影響多條數據的時候使用,例:搜索數據
key
的做用主要是爲了更高效的對比虛擬DOM中每一個節點是不是相同節點;Vue在patch
過程當中判斷兩個節點是不是相同節點,key是一個必要條件,渲染一組列表時,key每每是惟一標識,因此若是不定義key的話,Vue
只能認爲比較的兩個節點是同一個,哪怕它們實際上不是,這致使了頻繁更新元素,使得整個patch
過程比較低效,影響性能;undefined
,則可能永 遠認爲這是兩個相同的節點,只能去作更新操做,這形成了大量的dom更新操做,明顯是不可取的。父->子props
,子->父 $on、$emit` 獲取父子組件實例
children
Ref 獲取實例的方式調用組件的屬性或者方法
Provide、inject` 官方不推薦使用,可是寫組件庫時很經常使用
Event Bus
實現跨組件通訊 Vue.prototype.$bus = new Vue() Vuex
$attrs、$listeners
Provide、inject
當一個Vue實例建立時,Vue會遍歷data選項的屬性,用 Object.defineProperty 將它們轉爲 getter/setter而且在內部追蹤相關依賴,在屬性被訪問和修改時通知變化。每一個組件實例都有相應的 watcher 程序實例,它會在組件渲染的過程當中把屬性記錄爲依賴,以後當依賴項的 setter 被調用時,會通知 watcher從新計算,從而導致它關聯的組件得以更新。
vue
中雙向綁定是一個指令v-model
,能夠綁定一個動態值到視圖,同時視圖中變化能改變該值。v-model
是語法糖,默認狀況下相於:value和@input
。v-model
能夠減小大量繁瑣的事件處理代碼,提升開發效率,代碼可讀性也更好v-model
v-model
,自定義組件上若是要使用它須要在組件內綁定value並處理輸入事件v-model
模板的組件渲染函數,發現它會被轉換爲value屬性的綁定以及一個事件監聽,事件回調函數中會作相應變量更新操做,這說明神奇魔法其實是vue的編譯器完成的。nextTick
是Vue
提供的一個全局API
,是在下次DOM
更新循環結束以後執行延遲迴調,在修改數據以後使用$nextTick
,則能夠在回調中獲取更新後的DOM
;Vue
將開啓1個隊列,並緩衝在同一事件循環中發生的全部數據變動。若是同一個watcher
被屢次觸發,只會被推入到隊列中-次。這種在緩衝時去除重複數據對於避免沒必要要的計算和DOM
操做是很是重要的。nextTick
方法會在隊列中加入一個回調函數,確保該函數在前面的dom操做完成後才調用;nextTick
實現,它會在callbacks
裏面加入咱們傳入的函數,而後用timerFunc
異步方式調用它們,首選的異步方式會是Promise
。這讓我明白了爲何能夠在nextTick
中看到dom
操做結果。vnode 虛擬DOM節點 建立:
export function Vnode (){
return {
tag:'div',
children: 'span',
attr:'',
text:'你好!'
}
}
複製代碼
initProxy
:做用域代理,攔截組件內訪問其它組件的數據。initLifecycle
:創建父子組件關係,在當前組件實例上添加一些屬性和生命週期標識。如[Math Processing Error]parent,parent,refs,$children,_isMounted
等。initEvents
:對父組件傳入的事件添加監聽,事件是誰建立誰監聽,子組件建立事件子組件監聽initRender
:聲明[Math Processing Error]slots和slots和createElement()等。initInjections
:注入數據,初始化inject,通常用於組件更深層次之間的通訊。initState
:重要)數據響應式:初始化狀態。不少選項初始化的彙總:data,methods,props,computed和watch。initProvide
:提供數據注入。思考:爲何先注入再提供呢??
答:一、首先來自祖輩的數據要和當前實例的data,等判重,相結合,因此注入數據的initInjections必定要在InitState
的上面。2. 從上面注入進來的東西在當前組件中轉了一下又提供給後代了,因此注入數據也必定要在上面。
vm.[Math Processing Error]mount(vm.mount(vm.options.el)
:掛載實例。
做用:實現組件緩存
`activated `組件渲染後調用
`deactivated `組件銷燬後調用
複製代碼
原理:Vue.js
內部將DOM
節點抽象成了一個個的VNode
節點,keep-alive
組件的緩存也是基於VNode
節點的而不是直接存儲DOM
結構。它將知足條件(pruneCache與pruneCache)
的組件在cache
對象中緩存起來,在須要從新渲染的時候再將vnode
節點從cache
對象中取出並渲染。
include
字符串或正則表達式。只有名稱匹配的組件會被緩存
exclude
字符串或正則表達式。任何名稱匹配的組件都不會被緩存
max
數字、最多能夠緩存多少組件實例
vuex
是一個專門爲vue.js應用程序開發的狀態管理庫。 核心概念:
state
(單一狀態樹) getter/Mutation
顯示提交更改state
Action相似Mutation
,提交Mutation
,能夠包含任意異步操做。module
(當應用變得龐大複雜,拆分store
爲具體的module
模塊)在js中,渲染真實DOM
的開銷是很是大的, 好比咱們修改了某個數據,若是直接渲染到真實DOM
, 會引發整個dom
樹的重繪和重排。那麼有沒有可能實現只更新咱們修改的那一小塊dom而不要更新整個dom
呢?此時咱們就須要先根據真實dom
生成虛擬dom
, 當虛擬dom
某個節點的數據改變後會生成有一個新的Vnode
, 而後新的Vnode
和舊的Vnode
做比較,發現有不同的地方就直接修改在真實DOM上,而後使舊的Vnode
的值爲新的Vnode
。
diff的過程就是調用patch
函數,比較新舊節點,一邊比較一邊給真實的DOM
打補丁。在採起diff
算法比較新舊節點的時候,比較只會在同層級進行。 在patch
方法中,首先進行樹級別的比較 new Vnode
不存在就刪除 old Vnode
old Vnode
不存在就增長新的Vnode
都存在就執行diff更新 當肯定須要執行diff算法時,比較兩個Vnode
,包括三種類型操做:屬性更新,文本更新,子節點更新 新老節點均有子節點,則對子節點進行diff
操做,調用updatechidren
若是老節點沒有子節點而新節點有子節點,先清空老節點的文本內容,而後爲其新增子節點 若是新節點沒有子節點,而老節點有子節點的時候,則移除該節點的全部子節點 老新老節點都沒有子節點的時候,進行文本的替換
updateChildren 將Vnode
的子節點Vch和oldVnode的子節點oldCh提取出來。 oldCh和vCh
各有兩個頭尾的變量StartIdx和EndIdx
,它們的2個變量相互比較,一共有4種比較方式。若是4種比較都沒匹配,若是設置了key
,就會用key
進行比較,在比較的過程當中,變量會往中間靠,一旦StartIdx>EndIdx
代表oldCh和vCh
至少有一個已經遍歷完了,就會結束比較。
編碼階段
儘可能減小data中的數據,data中的數據都會增長getter和setter,會收集對應的watcher
v-if和v-for不能連用
若是須要使用v-for給每項元素綁定事件時使用事件代理
SPA 頁面採用keep-alive緩存組件
在更多的狀況下,使用v-if替代v-show
key保證惟一
使用路由懶加載、異步組件
防抖、節流
第三方模塊按需導入
長列表滾動到可視區域動態加載
圖片懶加載
SEO優化
預渲染
服務端渲染SSR
打包優化
壓縮代碼
Tree Shaking/Scope Hoisting
使用cdn加載第三方模塊
多線程打包happypack
splitChunks抽離公共文件
sourceMap優化
用戶體驗
骨架屏
PWA
還可使用緩存(客戶端緩存、服務端緩存)優化、服務端開啓gzip壓縮等。
複製代碼
更小巧、更快速 支持自定義渲染器 支持搖樹優化:一種在打包時去除無用代碼的優化手段 支持Fragments和跨組件渲染
模板語法99%保持不變 原生支持基於class的組件,而且無需藉助任何編譯及各類stage階段的特性 在設計時也考慮TypeScript的類型推斷特性 重寫虛擬DOM
能夠期待更多的編譯時提示來減小運行時的開銷 優化插槽生成
能夠單獨渲染父組件和子組件 靜態樹提高
下降渲染成本 基於Proxy的觀察者機制
節省內存開銷
檢測機制
更加全面、精準、高效,更具可調試式的響應跟蹤
Keys是React用於追蹤哪些列表中元素被修改、被添加或者被移除的輔助標識。
複製代碼
虛擬DOM
本質上是JavaScript
對象,是對真實DOM
的抽象表現。 狀態變動時,記錄新樹和舊樹的差別 最後把差別更新到真正的dom
中 render函數:
tagName
生成父標籤,讀取props
,設置屬性,若是有content
,設置innerHtml或innerText
,render
方法,將生成的子元素依次添加到父元素中,並返回根元素。Props
,子->父用callback
回調Event
模塊Redux、Mobx
等全局狀態管理管庫Context Api context
會使組件複用性變差Context
提供了一個無需爲每層組件手動添加 props
,就能在組件樹間進行數據傳遞的方法.若是你只是想避免層層傳遞一些屬性,組件組合(component composition
)有時候是一個比 context 更好的解決方案。 5. 組件組合缺點:會使高層組件變得複雜
調用React.createElement函數建立對象
複製代碼
componentWillMount、componentWillReceiveProps、componentWillUpdate在16版本被廢棄,在17版本將被刪除,須要使用UNSAVE_前綴使用,目的是向下兼容。
使用return null而不是CSS的display:none來控制節點的顯示隱藏。保證同一時間頁面的DOM節點儘量的少。
不要使用數組下標做爲key 利用 shouldComponentUpdate
和 PureComponent
避免過多 render function
; render
裏面儘可能減小新建變量和bind函數,傳遞參數是儘可能減小傳遞參數的數量。 儘可能將 props
和 state
扁平化,只傳遞 component
須要的 props
(傳得太多,或者層次傳得太深,都會加劇shouldComponentUpdate
裏面的數據比較負擔),慎將 component
看成 props
傳入
使用 babel-plugin-import
優化業務組件的引入,實現按需加載 使用 SplitChunksPlugin
拆分公共代碼 使用動態 import
,懶加載 React
組件
bind/箭頭函數
複製代碼
React Fiber 是一種基於瀏覽器的單線程調度算法.
複製代碼
setState
只在合成事件和鉤子函數中是「異步」的,在原生事件和 setTimeout 中都是同步的。setState
的「異步」並非說內部由異步代碼實現,其實自己執行的過程和代碼都是同步的,只是合成事件和鉤子函數的調用順序在更新以前,致使在合成事件和鉤子函數中無法立馬拿到更新後的值,形式了所謂的「異步」,固然能夠經過第二個參數 setState(partialState, callback) 中的callback拿到更新後的結果。setState
的批量更新優化也是創建在「異步」(合成事件、鉤子函數)之上的,在原生事件和setTimeout 中不會批量更新,在「異步」中若是對同一個值進行屢次 setState , setState 的批量更新策略會對其進行覆蓋,取最後一次的執行,若是是同時 setState 多個不一樣的值,在更新時會對其進行合併批量更新。Redux的實現流程
用戶頁面行爲觸發一個Action
,而後Store
調用Reducer
,而且傳入兩個參數:當前State
和收到的Action
。Reducer
會返回新的State
。每當state
更新以後,view
會根據state
觸發從新渲染。
React-Redux:
Provider
:從最外部封裝了整個應用,並向connect
模塊傳遞store
。 Connect
:
state
和action
經過props
的方式傳入到原組件內部。store tree
變化,使其包裝的原組件能夠響應state
變化高階組件是參數爲組件,返回值爲新組件的函數。HOC
是純函數,沒有反作用。HOC
在React
的第三方庫中很常見,例如Redux
的connect
組件。
高階組件的做用:
bootstrap
)代碼State
抽象和更改Props
更改React
組件?React.createClass()、ES6 class
和無狀態函數
React
元素與組件的區別?組件是由元素構成的。元素數據結構是普通對象,而組件數據結構是類或純函數。
數據流:
react主張函數式編程,因此推崇純組件,數據不可變,單向數據流,
vue的思想是響應式的,也就是基因而數據可變的,經過對每個屬性創建Watcher來監聽,當屬性變化的時候,響應式的更新對應的虛擬dom。
監聽數據變化實現原理:
Vue
經過 getter/setter
以及一些函數的劫持,能精確知道數據變化,不須要特別的優化就能達到很好的性能React
默認是經過比較引用的方式進行的,若是不優化(PureComponent/shouldComponentUpdate
)可能致使大量沒必要要的VDOM的從新渲染。組件通訊的區別:jsx和.vue模板。
HoC和Mixins
(在Vue中咱們組合不一樣功能的方式是經過Mixin
,而在React
中咱們經過HoC
(高階組件))。性能優化
React: shouldComponentUpdate
Vue
:內部實現shouldComponentUpdate
的優化,因爲依賴追蹤系統存在,經過watcher
判斷是否須要從新渲染(當一個頁面數據量較大時,Vue
的性能較差,形成頁面卡頓,因此通常數據比較大的項目傾向使用React
)。從實現原理上來講,最大的區別是兩點:
Redux使用的是不可變數據,而Vuex
的數據是可變的。Redux
每次都是用新的state
替換舊的state
,而Vuex
是直接修改
Redux在檢測數據變化的時候,是經過diff
的方式比較差別的,而Vuex
其實和Vue的原理同樣,是經過 getter/setter
來比較的(若是看Vuex
源碼會知道,其實他內部直接建立一個Vue
實例用來跟蹤數據變化)
三個方面:
網絡篇:
構建請求
查找強緩存
DNS解析
創建TCP鏈接(三次握手)
發送HTTP請求(網絡請求後網絡響應)
瀏覽器解析篇:
解析html構建DOM樹
解析css構建CSS樹、樣式計算
生成佈局樹(Layout Tree)
瀏覽器渲染篇:
創建圖層樹(Layer Tree)
生成繪製列表
生成圖塊並柵格化
顯示器顯示內容
最後斷開鏈接:TCP 四次揮手
(瀏覽器會將各層的信息發送給GPU,GPU會將各層合成,顯示在屏幕上)
複製代碼
1.`TCP`向上層提供面向鏈接的可靠服務 ,`UDP`向上層提供無鏈接不可靠服務。
2.雖然 `UDP` 並無 `TCP` 傳輸來的準確,可是也能在不少實時性要求高的地方有所做爲
3.對數據準確性要求高,速度能夠相對較慢的,能夠選用`TCP`
複製代碼
區別 | UDP | TCP |
---|---|---|
是否鏈接 | 無鏈接 | 面向鏈接 |
是否可靠 | 不可靠傳輸,不使用流量控制和擁塞控制 | 可靠傳輸,使用流量控制和擁塞控制 |
鏈接對象個數 | 支持一對一,一對多,多對一和多對多交互通訊 | 只能是一對一通訊 |
傳輸方式 | 面向報文 | 面向字節流 |
首部開銷 | 首部開銷小,僅8字節 | 首部最小20字節,最大60字節 |
適用場景 | 適用於實時應用(IP電話、視頻會議、直播等) | 適用於要求可靠傳輸的應用,例如文件傳輸 |
1.`HTTP` 的URL 以http:// 開頭,而HTTPS 的URL 以https:// 開頭
2.`HTTP` 是不安全的,而 HTTPS 是安全的
3.`HTTP` 標準端口是80 ,而 HTTPS 的標準端口是443
4.`在OSI` 網絡模型中,HTTP工做於應用層,而HTTPS 的安全傳輸機制工做在傳輸層
5.`HTTP` 沒法加密,而HTTPS 對傳輸的數據進行加密
6.`HTTP`無需證書,而HTTPS 須要CA機構wosign的頒發的SSL證書
複製代碼
1.GET在瀏覽器回退不會再次請求,POST會再次提交請求
2.GET請求會被瀏覽器主動緩存,POST不會,要手動設置
3.GET請求參數會被完整保留在瀏覽器歷史記錄裏,POST中的參數不會
4.GET請求在URL中傳送的參數是有長度限制的,而POST沒有限制
5.GET參數經過URL傳遞,POST放在Request body中
6.GET參數暴露在地址欄不安全,POST放在報文內部更安全
7.GET通常用於查詢信息,POST通常用於提交某種信息進行某些修改操做
8.GET產生一個TCP數據包;POST產生兩個TCP數據包
複製代碼
XSS
(Cross-Site Scripting
,跨站腳本攻擊)是一種代碼注入攻擊。攻擊者在目標網站上注入惡意代碼,當被攻擊者登錄網站時就會執行這些惡意代碼,這些腳本能夠讀取 cookie,session tokens
,或者其它敏感的網站信息,對用戶進行釣魚欺詐,甚至發起蠕蟲攻擊等。
CSRF
(Cross-site request forgery
)跨站請求僞造:攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站發送跨站請求。利用受害者在被攻擊網站已經獲取的註冊憑證,繞事後臺的用戶驗證,達到冒充用戶對被攻擊的網站執行某項操做的目的。
XSS避免方式:
url
參數使用encodeURIComponent
方法轉義InnerHtml
插入HTML
內容CSRF
避免方式:
DDoS
又叫分佈式拒絕服務,全稱 Distributed Denial of Service
,其原理就是利用大量的請求形成資源過載,致使服務不可用。
DDos
避免方式:
ICMP
包等好比:
200響應成功
301永久重定向
302臨時重定向
304資源緩存
403服務器禁止訪問
404服務器資源未找到
500 502服務器內部錯誤
504 服務器繁忙
1xx Informational(信息狀態碼) 接受請求正在處理
2xx Success(成功狀態碼) 請求正常處理完畢
3xx Redirection(重定向狀態碼) 須要附加操做已完成請求
4xx Client Error(客戶端錯誤狀態碼) 服務器沒法處理請求
5xx Server Error(服務器錯誤狀態碼) 服務器處理請求出錯
複製代碼
剛開始雙方都處於 establised
狀態,假如是客戶端先發起關閉請求,則:
創建TCP鏈接->發送請求行->發送請求頭->(到達服務器)發送狀態行->發送響應頭->發送響應數據->斷TCP鏈接
1. 瀏覽器緩存
2. 防抖、節流
3. 資源懶加載、預加載
4.開啓Nginx gzip壓縮
三個方面來講明前端性能優化
一: webapck優化與開啓gzip壓縮
1.babel-loader用 include 或 exclude 來幫咱們避免沒必要要的轉譯,不轉譯node_moudules中的js文件
其次在緩存當前轉譯的js文件,設置loader: 'babel-loader?cacheDirectory=true'
2.文件採用按需加載等等
3.具體的作法很是簡單,只須要你在你的 request headers 中加上這麼一句:
accept-encoding:gzip
4.圖片優化,採用svg圖片或者字體圖標
5.瀏覽器緩存機制,它又分爲強緩存和協商緩存
二:本地存儲——從 Cookie 到 Web Storage、IndexedDB
說明一下SessionStorage和localStorage還有cookie的區別和優缺點
三:代碼優化
1.事件代理
2.事件的節流和防抖
3.頁面的迴流和重繪
4.EventLoop事件循環機制
5.代碼優化等等
複製代碼
一個域下的js腳本未經容許的狀況下,不能訪問另外一個域下的內容。一般判斷跨域的依據是協議、域名、端口號是否相同,不一樣則跨域。同源策略是對js腳本的一種限制,並非對瀏覽器的限制,像img,script腳本請求不會有跨域限制。
Ajax : 短鏈接
Websocket : 長鏈接,雙向的。
Form表單(最原始的)
複製代碼
解決方案:
jsonp
(利用script
標籤沒有跨域限制的漏洞實現。缺點:只支持GET
請求)CORS
(設置Access-Control-Allow-Origin
:指定可訪問資源的域名)postMessage
(message, targetOrigin, [transfer]
)(HTML5
新增API 用於多窗口消息、頁面內嵌iframe消息傳遞),經過onmessage
監聽 傳遞過來的數據Websocket
是HTML5的一個持久化的協議,它實現了瀏覽器與服務器的全雙工通訊,同時也是跨域的一種解決方案。Node
中間件代理Nginx
反向代理iframe
的方式,不經常使用。瀏覽器的本地存儲主要分爲Cookie、WebStorage和IndexDB
, 其中WebStorage
又能夠分爲localStorage和sessionStorage
。
共同點: 都是保存在瀏覽器端、且同源的
不一樣點:
cookie
數據始終在同源的http
請求中攜帶(即便不須要),即cookie
在瀏覽器和服務器間來回傳遞。cookie
數據還有路徑(path
)的概念,能夠限制cookie
只屬於某個路徑下sessionStorage
和localStorage
不會自動把數據發送給服務器,僅在本地保存。cookie
數據不能超過4K,sessionStorage和localStorage
能夠達到5MsessionStorage
:僅在當前瀏覽器窗口關閉以前有效;localStorage
:始終有效,窗口或瀏覽器關閉也一直保存,本地存儲,所以用做持久數據;cookie
:只在設置的cookie
過時時間以前有效,即便窗口關閉或瀏覽器關閉sessionStorage
:不在不一樣的瀏覽器窗口中共享,即便是同一個頁面;localstorage
:在全部同源窗口中都是共享的;也就是說只要瀏覽器不關閉,數據仍然存在cookie
: 也是在全部同源窗口中都是共享的.也就是說只要瀏覽器不關閉,數據仍然存在module.exports={
entry: {},
output: {},
plugins: [],
module: [rules:[{}]]
}
複製代碼
入口起點
:使用 entry
配置手動地分離代碼。防止重複
:使用 CommonsChunkPlugin
去重和分離 chunk
。動態導入
:經過模塊的內聯函數調用來分離代碼。loader
: 是一個導出爲函數的javascript
模塊,根據rule
匹配文件擴展名,處理文件的轉換器。
file-loader
:把文件輸出到一個文件夾中,在代碼中經過相對 URL
去引用輸出的文件 (處理圖片和字體)
url-loader
: 與file-loader
相似,區別是用戶能夠設置一個閾值,大於閾值會交給file-loader
處理,小於閾值時返回文件base64
形式編碼 (處理圖片和字體)
image-loader
:加載而且壓縮圖片文件
babel-loader
:把 ES6
轉換成 ES5
sass-loader
:將SCSS/SASS
代碼轉換成CSS
css-loader
:加載 CSS
,支持模塊化、壓縮、文件導入等特性
style-loader
:把 CSS
代碼注入到 JavaScript
中,經過 DOM
操做去加載 CSS
postcss-loader
:擴展 CSS
語法,使用下一代 CSS
,能夠配合 autoprefixer
插件自動補齊 CSS3 前綴 eslint-loader
:經過 ESLint
檢查 JavaScript
代碼
plugin:本質是插件,基於事件流框架 Tapable
,插件能夠擴展 Webpack
的功能,在 Webpack
運行的生命週期中會廣播出許多事件,Plugin
能夠監聽這些事件,在合適的時機經過 Webpack
提供的 API
改變輸出結果。
html-webpack-plugin
:簡化 HTML
文件建立 (依賴於 html-loader
)
uglifyjs-webpack-plugin
:壓縮js文件
clean-webpack-plugin
:目錄清除
mini-css-extract-plugin
:分離樣式文件,CSS 提取爲獨立文件,支持按需加載 (替代extract-text-webpack-plugin
)
Loader
在 module.rules
中配置,做爲模塊的解析規則,類型爲數組。每一項都是一個 Object
,內部包含了 test(類型文件)、loader、options
(參數)等屬性。Plugin
在 plugins
中單獨配置,類型爲數組,每一項是一個Plugin
的實例,參數都經過構造函數傳入。CommonJS
是服務器端模塊的規範,由Node推廣使用,webpack也採用這種規範編寫
CommonJS
模塊規範主要分爲三部分:模塊定義、模塊標識、模塊引用
。
模塊定義:module
對象:在每個模塊中,module
對象表明該模塊自身。 export
屬性:module
對象的一個屬性,它向外提供接口。輸出模塊變量的最好方法是使用module.exports
對象。一個單獨的文件就是一個模塊。每個模塊都是一個單獨的做用域,也就是說,在該模塊內部定義的變量,沒法被其餘模塊讀取,除非定義爲global
對象的屬性。
模塊標識:傳遞給require
方法的參數,必須是符合小駝峯命名的字符串,或者以 . 、.. 、開頭的相對路徑,或者絕對路徑。
模塊引用:加載模塊使用require
(同步加載),該方法讀取一個文件並執行,返回文件內部的module.exports
對象。
在後端,JavaScript
的規範遠遠落後而且有不少缺陷,這使得難以使用JavaScript
開發大型應用。好比:沒有模塊系統、標準庫較少、沒有標準接口、缺少包管理系統、列表內容
CommonJS模塊規範很好地解決變量污染問題,每一個模塊具備獨立空間,互不干擾,命名空間相比之下就不太好。
CommonJS規範定義模塊十分簡單,接口十分簡潔。
CommonJS模塊規範支持引入和導出功能,這樣能夠順暢地鏈接各個模塊,實現彼此間的依賴關係
CommonJS規範的提出,主要是爲了彌補JavaScript沒有標準的缺陷,已達到像Python、Ruby和Java那樣具有開發大型應用的基礎能力,而不是停留在開發瀏覽器端小腳本程序的階段
沒有並行加載機制
因爲CommonJS
是同步加載模塊,這對於服務器端是很很差的,由於全部的模塊都放在本地硬盤。等待模塊時間就是硬盤讀取文件時間,很小。可是,對於瀏覽器而言,它須要從服務器加載模塊,涉及到網速,代理等緣由,一旦等待時間過長,瀏覽器處於」假死」狀態。
因此瀏覽器端不是很適合Common.Js
,出現另外一種規範AMD
AMD
是運行在瀏覽器環境的一個異步模塊定義規範 ,是RequireJS
在推廣過程當中對模塊定義的規範化產出。
AMD
推崇依賴前置,在定義模塊的時候就要聲明其依賴的模塊
用戶體驗好,由於沒有延遲,依賴模塊提早執行了。
CMD
是一個通用模塊定義規範;是SeaJs推廣過程當中對模塊定義的規範化產出
CMD
推崇依賴就近,只有在用到某個模塊的時候纔會去require
性能好,由於只有用戶須要的時候才執行。
防抖節流
函數防抖關注必定時間連續觸發,只在最後執行一次,而函數節流側重於一段時間內只執行一次。
//定義:觸發事件後在n秒內函數只能執行一次,若是在n秒內又觸發了事件,則會從新計算函數執行時間。
//搜索框搜索輸入。只需用戶最後一次輸入完,再發送請求
//手機號、郵箱驗證輸入檢測 onchange oninput事件
//窗口大小Resize。只需窗口調整完成後,計算窗口大小。防止重複渲染。
const debounce = (fn, wait, immediate) => {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
if (immediate && !timer) {
fn.call(this, args);
}
timer = setTimeout(() => {
fn.call(this, args);
}, wait);
};
};
const betterFn = debounce(() => console.log("fn 防抖執行了"), 1000, true);
document.addEventListener("scroll", betterFn);
複製代碼
//定義:當持續觸發事件時,保證隔間時間觸發一次事件。
//1. 懶加載、滾動加載、加載更多或監聽滾動條位置;
//2. 百度搜索框,搜索聯想功能;
//3. 防止高頻點擊提交,防止表單重複提交;
function throttle(fn,wait){
let pre = 0;
return function(...args){
let now = Date.now();
if( now - pre >= wait){
fn.apply(this,args);
pre = now;
}
}
}
function handle(){
console.log(Math.random());
}
window.addEventListener("mousemove",throttle(handle,1000));
複製代碼
//淺拷貝
1. Object.assign(target,source)
2. es6對象擴展運算符。
//深拷貝
function deepClone(obj) {
if (!obj || typeof obj !== "object") return;
let newObj = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === "object" ? deepClone(obj[key]) : obj[key];
}
}
return newObj;
}
複製代碼
//數組
const arr = [2,7,5,7,2,8,9];
console.log([...new Set(arr)]); // [2,7,5,8,9];
//對象
const list = [{age:18,name:'張三'},{age:18,name:'李四'},{age:18,name:'王五'}]
let hash = {};
const newArr = arr.reduce((item, next) => {
hash[next.age] ? '' : hash[next.age] = true && item.push(next);
return item;
}, []);
console.log(list);
複製代碼
function flatten(arr) {
return arr.reduce((result, item) => {
return result.concat(Array.isArray(item) ? flatten(item) : item);
}, []);
}
複製代碼
它的功能相似於一種標識惟一性的ID,每一個Symbol
實例都是惟一的。 Symbol
類型的key是不能經過Object.keys()
或者for...in
來枚舉的, 它未被包含在對象自身的屬性名集合(property names
)之中。 因此,利用該特性,咱們能夠把一些不須要對外操做和訪問的屬性使用Symbol來定義。 // 使用Object的API
Object.getOwnPropertySymbols(obj)
// [Symbol(name)]
// 使用新增的反射API Reflect.ownKeys(obj)
// [Symbol(name), 'age', 'title']
Map
對象保存鍵值對。任何值(對象或者原始值) 均可以做爲一個鍵或一個值。構造函數Map能夠接受一個數組做爲參數。Set
對象容許你存儲任何類型的值,不管是原始值或者是對象引用。它相似於數組,可是成員的值都是惟一的,沒有重複的值。key
的做用主要是爲了高效的更新虛擬DOM
,其原理是vue
在patch
過程當中經過key
能夠精準判斷兩個節點是不是同一個,從而避免頻繁更新不一樣元素,使得整個patch
過程更加高效,減小DOM
操做量,提升性能。 2. 另外,若不設置key
還可能在列表更新時引起一些隱蔽的bug 3. vue
中在使用相同標籤名元素的過渡切換時,也會使用到key屬性,其目的也是爲了讓vue能夠區分它們, 不然vue
只會替換其內部屬性而不會觸發過渡效果。
arguments
,取而代之用rest
參數...解決this
,會捕獲其所在的上下文的this值,做爲本身的this值call() 或 apply()
方法調用一個函數時,只傳入了一個參數,對 this 並無影響。Generator
函數,不能使用yield
關鍵字總結:
this
永遠指向其上下文的 this
,任何方法都改變不了其指向,如call() , bind() , apply()
// 普通的add函數
function add(x, y) {
return x + y
}
// Currying後
function curryingAdd(x) {
return function (y) {
return x + y
}
}
add(1, 2) // 3
curryingAdd(1)(2) // 3
複製代碼
原型鏈繼承 寫個父類、子類 子類的原型爲父類的實例 子類.prootype = new 父類 修正子類原型爲子類自己 子類.prototype.constructor=子類 new 子類便可調用父類方法 構造函數繼承 寫個父類、子類 在子類中父類.call(this) 便可實現
當一個組件須要獲取多個狀態時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。爲了解決這個問題,咱們可使用 mapState 輔助函數幫助咱們生成計算屬性 mapMutations 其實跟mapState 的做用是相似的,將組件中的 methods 映射爲 store.commit 調用
如上圖能夠粗略的分爲兩類,多項式量級和非多項式量級。其中,非多項式量級只有兩個:O(2n) 和 O(n!) 對應的增加率以下圖所示
xxxxx...
osi7層模型:物理層-數據鏈路層-傳輸層-網絡層-應用層-會話層-表示層
tcp5層模型:物理層-數據鏈路層-傳輸層-網絡層-應用層
我是伊人a,與你相逢,我很開心。
文中若有錯誤,歡迎在評論區指正,若是這篇文章幫到了你,歡迎點贊👍和關注😊
本文首發於掘金,未經許可禁止轉載💌