整理了一張前端面試思惟導圖我放在了文章最後面,因爲圖片太大,建議下載查看。javascript
本文整理了面試大體思路以及一些基礎知識點,但願能給你帶去些許幫助,助力你找到心儀的好工做。css
自我介紹(僅供參考)
注意點(克服緊張,語速放慢,目光直視面試官)html
面試官下午好,我叫**,今天來應聘貴公司的前端工程師崗位。我從事前端開發兩年多,有X年多的Vue開發經驗,一年React開發經驗,在上家公司主要從事H5頁面,後臺管理系統,混合App等項目開發。日常喜歡逛一些技術社區豐富本身的技術,像思否,掘金之類,而且本身也獨立開發了我的博客網站,記錄本身的工做總結和學習心得。 個人性格比較溫和,跟同事朋友相處時比較外向,在工做中代碼開發時我喜歡全心全意的投入,對於工做我總抱着認真負責的態度。面試官,以上是個人介紹,謝謝。前端
項目具體介紹
這部分大機率會問,注意語言措辭,作好充足的準備沒你就不會慌張,安全感是本身給本身的。 示例:vue
XXAPP
項目簡介:XXAPP是一款多功能的民營銀行軟件,主要有帳戶交易、轉帳匯款、存單產品買入賣出、充值提現等功能,使用原生內嵌webview的方式,通訊方面iOS採用messageHandlers[fn].postMessage(data)
方法。Android
採用window.AndroidWebView[fn] (data)
html5
項目亮點及難點:登陸超時從新登陸後繼續返回原先操做的頁面。java
xxx銀行項目
xxx商城
xxx後臺管理系統
xxx
HTML、CSS相關
html5新特性、語義化
- 語義化標籤 : header nav main article section aside footer
語義化意味着顧名思義,HTML5的語義化指的是合理正確的使用語義化的標籤來建立頁面結構,如
header,footer,nav,從標籤上便可以直觀的知道這個標籤的做用,而不是濫用div。
語義化的優勢有:
代碼結構清晰,易於閱讀,利於開發和維護
方便其餘設備解析(如屏幕閱讀器)根據語義渲染網頁。
有利於搜索引擎優化(SEO),搜索引擎爬蟲會根據不一樣的標籤來賦予不一樣的權重
複製代碼
瀏覽器渲染機制、重繪、重排
網頁生成過程:node
HTML
被HTML解析器解析成DOM
樹css
則被css解析器解析成CSSOM
樹- 結合
DOM
樹和CSSOM
樹,生成一棵渲染樹(Render Tree
) - 生成佈局(
flow
),即將全部渲染樹的全部節點進行平面合成 - 將佈局繪製(
paint
)在屏幕上
重排(也稱迴流): 當DOM
的變化影響了元素的幾何信息(DOM
對象的位置和尺寸大小),瀏覽器須要從新計算元素的幾何屬性,將其安放在界面中的正確位置,這個過程叫作重排。 觸發:react
- 添加或者刪除可見的DOM元素
- 元素尺寸改變——邊距、填充、邊框、寬度和高度
重繪: 當一個元素的外觀發生改變,但沒有改變佈局,從新把元素外觀繪製出來的過程,叫作重繪。 觸發:webpack
- 改變元素的
color、background、box-shadow
等屬性
重排優化建議:
- 分離讀寫操做
- 樣式集中修改
- 緩存須要修改的
DOM
元素 - 儘可能只修改
position:absolute
或fixed
元素,對其餘元素影響不大 - 動畫開始
GPU
加速,translate
使用3D
變化
transform
不重繪,不迴流 是由於transform
屬於合成屬性,對合成屬性進行transition/animate
動畫時,將會建立一個合成層。這使得動畫元素在一個獨立的層中進行渲染。當元素的內容沒有發生改變,就沒有必要進行重繪。瀏覽器會經過從新複合來建立動畫幀。
css盒子模型
全部HTML
元素能夠看做盒子,在CSS中,"box model"
這一術語是用來設計和佈局時使用。 CSS
盒模型本質上是一個盒子,封裝周圍的HTML
元素,它包括:邊距,邊框,填充,和實際內容。 盒模型容許咱們在其它元素和周圍元素邊框之間的空間放置元素。
css樣式優先級
!important>style>id>class
什麼是BFC?BFC的佈局規則是什麼?如何建立BFC?BFC應用?
BFC
是 Block Formatting Context
的縮寫,即塊格式化上下文。BFC
是CSS佈局的一個概念,是一個環境,裏面的元素不會影響外面的元素。 佈局規則:Box是CSS佈局的對象和基本單位,頁面是由若干個Box組成的。元素的類型和display屬性,決定了這個Box的類型。不一樣類型的Box會參與不一樣的Formatting Context
。 建立:浮動元素 display:inline-block position:absolute
應用: 1.分屬於不一樣的BFC
時,能夠防止margin
重疊 2.清除內部浮動 3.自適應多欄佈局
DOM、BOM對象
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 元素的對象和屬性,以及訪問它們的方法。
JS相關
js數據類型、typeof、instanceof、類型轉換
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指向、new關鍵字
this
對象是是執行上下文中的一個屬性,它指向最後一次調用這個方法的對象,在全局函數中,this
等於window
,而當函數被做爲某個對象調用時,this等於那個對象。 在實際開發中,this
的指向能夠經過四種調用模式來判斷。
- 函數調用,當一個函數不是一個對象的屬性時,直接做爲函數來調用時,
this
指向全局對象。 - 方法調用,若是一個函數做爲一個對象的方法來調用時,
this
指向這個對象。 - 構造函數調用,
this
指向這個用new
新建立的對象。 - 第四種是
apply 、 call 和 bind
調用模式,這三個方法均可以顯示的指定調用函數的 this 指向。apply
接收參數的是數組,call
接受參數列表,`` bind方法經過傳入一個對象,返回一個
this綁定了傳入對象的新函數。這個函數的
this指向除了使用
new `時會被改變,其餘狀況下都不會改變。
new
- 首先建立了一個新的空對象
- 設置原型,將對象的原型設置爲函數的
prototype
對象。 - 讓函數的
this
指向這個對象,執行構造函數的代碼(爲這個新對象添加屬性) - 判斷函數的返回值類型,若是是值類型,返回建立的對象。若是是引用類型,就返回這個引用類型的對象。
做用域、做用域鏈、變量提高
做用域
負責收集和維護由全部聲明的標識符(變量)組成的一系列查詢,並實施一套很是嚴格的規則,肯定當前執行的代碼對這些標識符的訪問權限。(全局做用域、函數做用域、塊級做用域)。 做用域鏈就是從當前做用域開始一層一層向上尋找某個變量,直到找到全局做用域仍是沒找到,就宣佈放棄。這種一層一層的關係,就是做用域鏈
。
繼承(含es6)、多種繼承方式
(1)第一種是以原型鏈的方式來實現繼承
,可是這種實現方式存在的缺點是,在包含有引用類型的數據時,會被全部的實例對象所共享,容易形成修改的混亂。還有就是在建立子類型的時候不能向超類型傳遞參數。
(2)第二種方式是使用借用構造函數
的方式,這種方式是經過在子類型的函數中調用超類型的構造函數來實現的,這一種方法解決了不能向超類型傳遞參數的缺點,可是它存在的一個問題就是沒法實現函數方法的複用,而且超類型原型定義的方法子類型也沒有辦法訪問到。
(3)第三種方式是組合繼承
,組合繼承是將原型鏈和借用構造函數組合起來使用的一種方式。經過借用構造函數的方式來實現類型的屬性的繼承,經過將子類型的原型設置爲超類型的實例來實現方法的繼承。這種方式解決了上面的兩種模式單獨使用時的問題,可是因爲咱們是以超類型的實例來做爲子類型的原型,因此調用了兩次超類的構造函數,形成了子類型的原型中多了不少沒必要要的屬性。
(4)第四種方式是原型式繼承
,原型式繼承的主要思路就是基於已有的對象來建立新的對象,實現的原理是,向函數中傳入一個對象,而後返回一個以這個對象爲原型的對象。這種繼承的思路主要不是爲了實現創造一種新的類型,只是對某個對象實現一種簡單繼承,ES5 中定義的 Object.create() 方法就是原型式繼承的實現。缺點與原型鏈方式相同。
(5)第五種方式是寄生式繼承
,寄生式繼承的思路是建立一個用於封裝繼承過程的函數,經過傳入一個對象,而後複製一個對象的副本,而後對象進行擴展,最後返回這個對象。這個擴展的過程就能夠理解是一種繼承。這種繼承的優勢就是對一個簡單對象實現繼承,若是這個對象不是咱們的自定義類型時。缺點是沒有辦法實現函數的複用。
(6)第六種方式是寄生式組合繼承
,組合繼承的缺點就是使用超類型的實例作爲子類型的原型,致使添加了沒必要要的原型屬性。寄生式組合繼承的方式是使用超類型的原型的副原本做爲子類型的原型,這樣就避免了建立沒必要要的屬性。
EventLoop
JS
是單線程的,爲了防止一個函數執行時間過長阻塞後面的代碼,因此會先將同步代碼壓入執行棧中,依次執行,將異步代碼推入異步隊列,異步隊列又分爲宏任務隊列和微任務隊列,由於宏任務隊列的執行時間較長,因此微任務隊列要優先於宏任務隊列。微任務隊列的表明就是,Promise.then
,MutationObserver
,宏任務的話就是setImmediate setTimeout setInterval
原生ajax
ajax是一種異步通訊的方法,從服務端獲取數據,達到局部刷新頁面的效果。 過程:
- 建立
XMLHttpRequest
對象; - 調用
open
方法傳入三個參數 請求方式(GET/POST)、url、同步異步(true/false)
; - 監聽
onreadystatechange
事件,當readystate
等於4時返回responseText
; - 調用send方法傳遞參數。
事件冒泡、捕獲(委託)
- 事件冒泡指在在一個對象上觸發某類事件,若是此對象綁定了事件,就會觸發事件,若是沒有,就會向這個對象的父級對象傳播,最終父級對象觸發了事件。
- 事件委託本質上是利用了瀏覽器事件冒泡的機制。由於事件在冒泡過程當中會上傳到父節點,而且父節點能夠經過事件對象獲取到目標節點,所以能夠把子節點的監聽函數定義在父節點上,由父節點的監聽函數統一處理多個子元素的事件,這種方式稱爲事件代理。
event.stopPropagation()
或者 ie下的方法 event.cancelBubble = true;
//阻止事件冒泡
ES6
- 新增symbol類型 表示獨一無二的值,用來定義獨一無二的對象屬性名;
- const/let 都是用來聲明變量,不可重複聲明,具備塊級做用域。存在暫時性死區,也就是不存在變量提高。(const通常用於聲明常量);
- 變量的解構賦值(包含數組、對象、字符串、數字及布爾值,函數參數),剩餘運算符(...rest);
- 模板字符串(
${data}
); - 擴展運算符(數組、對象);;
- 箭頭函數;
- Set和Map數據結構;
- Proxy/Reflect;
- Promise;
- async函數;
- Class;
- Module語法(import/export)。
Vue
簡述MVVM
MVVM是Model-View-ViewModel
縮寫,也就是把MVC
中的Controller
演變成ViewModel。Model
層表明數據模型,View
表明UI組件,ViewModel
是View
和Model
層的橋樑,數據會綁定到viewModel
層並自動將數據渲染到頁面中,視圖變化的時候會通知viewModel
層更新數據。
談談對vue生命週期的理解?
每一個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
:當一條數據影響多條數據的時候使用,例:搜索數據
v-for中key的做用
key
的做用主要是爲了更高效的對比虛擬DOM中每一個節點是不是相同節點;Vue在patch
過程當中判斷兩個節點是不是相同節點,key是一個必要條件,渲染一組列表時,key每每是惟一標識,因此若是不定義key的話,Vue
只能認爲比較的兩個節點是同一個,哪怕它們實際上不是,這致使了頻繁更新元素,使得整個patch
過程比較低效,影響性能;- 從源碼中能夠知道,Vue判斷兩個節點是否相同時主要判斷二者的key和元素類型等,所以若是不設置key,它的值就是
undefined
,則可能永 遠認爲這是兩個相同的節點,只能去作更新操做,這形成了大量的dom更新操做,明顯是不可取的。
vue組件的通訊方式
父子組件通訊
父->子props
,子->父 $on、$emit` 獲取父子組件實例
parent、parent、parent、children
Ref 獲取實例的方式調用組件的屬性或者方法
Provide、inject` 官方不推薦使用,可是寫組件庫時很經常使用
兄弟組件通訊
Event Bus
實現跨組件通訊 Vue.prototype.$bus = new Vue() Vuex
跨級組件通訊
$attrs、$listeners
Provide、inject
經常使用指令
- v-if:判斷是否隱藏;
- v-for:數據循環出來;
- v-bind:class:綁定一個屬性;
- v-model:實現雙向綁定
雙向綁定實現原理
當一個Vue實例建立時,Vue會遍歷data選項的屬性,用 Object.defineProperty 將它們轉爲 getter/setter而且在內部追蹤相關依賴,在屬性被訪問和修改時通知變化。每一個組件實例都有相應的 watcher 程序實例,它會在組件渲染的過程當中把屬性記錄爲依賴,以後當依賴項的 setter 被調用時,會通知 watcher從新計算,從而導致它關聯的組件得以更新。
v-model的實現以及它的實現原理嗎?
vue
中雙向綁定是一個指令v-model
,能夠綁定一個動態值到視圖,同時視圖中變化能改變該值。v-model
是語法糖,默認狀況下相於:value和@input
。- 使用
v-model
能夠減小大量繁瑣的事件處理代碼,提升開發效率,代碼可讀性也更好 - 一般在表單項上使用
v-model
- 原生的表單項能夠直接使用
v-model
,自定義組件上若是要使用它須要在組件內綁定value並處理輸入事件 - 我作過測試,輸出包含
v-model
模板的組件渲染函數,發現它會被轉換爲value屬性的綁定以及一個事件監聽,事件回調函數中會作相應變量更新操做,這說明神奇魔法其實是vue的編譯器完成的。
nextTick的實現
nextTick
是Vue
提供的一個全局API
,是在下次DOM
更新循環結束以後執行延遲迴調,在修改數據以後使用$nextTick
,則能夠在回調中獲取更新後的DOM
;- Vue在更新DOM時是異步執行的。只要偵聽到數據變化,
Vue
將開啓1個隊列,並緩衝在同一事件循環中發生的全部數據變動。若是同一個watcher
被屢次觸發,只會被推入到隊列中-次。這種在緩衝時去除重複數據對於避免沒必要要的計算和DOM
操做是很是重要的。nextTick
方法會在隊列中加入一個回調函數,確保該函數在前面的dom操做完成後才調用; - 好比,我在幹什麼的時候就會使用nextTick,傳一個回調函數進去,在裏面執行dom操做便可;
- 我也有簡單瞭解
nextTick
實現,它會在callbacks
裏面加入咱們傳入的函數,而後用timerFunc
異步方式調用它們,首選的異步方式會是Promise
。這讓我明白了爲何能夠在nextTick
中看到dom
操做結果。
vnode的理解,compiler和patch的過程
vnode 虛擬DOM節點 建立: export function Vnode (){ return { tag:'div', children: 'span', attr:'', text:'你好!' } } 複製代碼
new Vue後整個的流程
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)
:掛載實例。
keep-alive的實現
做用:實現組件緩存
鉤子函數:
`activated `組件渲染後調用
`deactivated `組件銷燬後調用
複製代碼
原理:Vue.js
內部將DOM
節點抽象成了一個個的VNode
節點,keep-alive
組件的緩存也是基於VNode
節點的而不是直接存儲DOM
結構。它將知足條件(pruneCache與pruneCache)
的組件在cache
對象中緩存起來,在須要從新渲染的時候再將vnode
節點從cache
對象中取出並渲染。
配置屬性:
include
字符串或正則表達式。只有名稱匹配的組件會被緩存
exclude
字符串或正則表達式。任何名稱匹配的組件都不會被緩存
max
數字、最多能夠緩存多少組件實例
vuex、vue-router實現原理
vuex
是一個專門爲vue.js應用程序開發的狀態管理庫。 核心概念:
state
(單一狀態樹)getter/Mutation
顯示提交更改state
Action相似Mutation
,提交Mutation
,能夠包含任意異步操做。module
(當應用變得龐大複雜,拆分store
爲具體的module
模塊)
你怎麼理解Vue中的diff算法?
在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
至少有一個已經遍歷完了,就會結束比較。
你都作過哪些Vue的性能優化?
編碼階段 儘可能減小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壓縮等。 複製代碼
你知道Vue3有哪些新特性嗎?它們會帶來什麼影響?
- 性能提高
更小巧、更快速 支持自定義渲染器 支持搖樹優化:一種在打包時去除無用代碼的優化手段 支持Fragments和跨組件渲染
- API變更
模板語法99%保持不變 原生支持基於class的組件,而且無需藉助任何編譯及各類stage階段的特性 在設計時也考慮TypeScript的類型推斷特性 重寫虛擬DOM
能夠期待更多的編譯時提示來減小運行時的開銷 優化插槽生成
能夠單獨渲染父組件和子組件 靜態樹提高
下降渲染成本 基於Proxy的觀察者機制
節省內存開銷
- 不兼容IE11
檢測機制
更加全面、精準、高效,更具可調試式的響應跟蹤
實現雙向綁定 Proxy 與 Object.defineProperty 相比優劣如何?
- Object.definedProperty的做用是劫持一個對象的屬性,劫持屬性的getter和setter方法,在對象的屬性發生變化時進行特定的操做。而 Proxy劫持的是整個對象。
- Proxy會返回一個代理對象,咱們只須要操做新對象便可,而Object.defineProperty只能遍歷對象屬性直接修改。
- Object.definedProperty不支持數組,更準確的說是不支持數組的各類API,由於若是僅僅考慮arry[i] = value 這種狀況,是能夠劫持 的,可是這種劫持意義不大。而Proxy能夠支持數組的各類API。
- 儘管Object.defineProperty有諸多缺陷,可是其兼容性要好於Proxy。
React
一、react中key的做用,有key沒key有什麼區別,比較同一層級節點什麼意思?
Keys是React用於追蹤哪些列表中元素被修改、被添加或者被移除的輔助標識。
複製代碼
二、你對虛擬dom和diff算法的理解,實現render函數
虛擬DOM
本質上是JavaScript
對象,是對真實DOM
的抽象表現。 狀態變動時,記錄新樹和舊樹的差別 最後把差別更新到真正的dom
中 render函數:
- 根據
tagName
生成父標籤,讀取props
,設置屬性,若是有content
,設置innerHtml或innerText
, - 若是存在子元素,遍歷子元素遞歸調用
render
方法,將生成的子元素依次添加到父元素中,並返回根元素。
三、React組件之間通訊方式?
- 父子組件,父->子直接用
Props
,子->父用callback
回調 - 非父子組件,用發佈訂閱模式的
Event
模塊 - 項目複雜的話用
Redux、Mobx
等全局狀態管理管庫 Context Api context
會使組件複用性變差
Context
提供了一個無需爲每層組件手動添加 props
,就能在組件樹間進行數據傳遞的方法.若是你只是想避免層層傳遞一些屬性,組件組合(component composition
)有時候是一個比 context 更好的解決方案。 5. 組件組合缺點:會使高層組件變得複雜
四、如何解析jsx
調用React.createElement函數建立對象
複製代碼
五、生命週期都有哪幾種,分別是在什麼階段作哪些事情?爲何要廢棄一些生命週期?
componentWillMount、componentWillReceiveProps、componentWillUpdate在16版本被廢棄,在17版本將被刪除,須要使用UNSAVE_前綴使用,目的是向下兼容。
六、關於react的優化方法
- 代碼層面:
使用return null而不是CSS的display:none來控制節點的顯示隱藏。保證同一時間頁面的DOM節點儘量的少。
- props和state的數據儘量簡單明瞭,扁平化。
不要使用數組下標做爲key 利用 shouldComponentUpdate
和 PureComponent
避免過多 render function
; render
裏面儘可能減小新建變量和bind函數,傳遞參數是儘可能減小傳遞參數的數量。 儘可能將 props
和 state
扁平化,只傳遞 component
須要的 props
(傳得太多,或者層次傳得太深,都會加劇shouldComponentUpdate
裏面的數據比較負擔),慎將 component
看成 props
傳入
- 代碼體積:
使用 babel-plugin-import
優化業務組件的引入,實現按需加載 使用 SplitChunksPlugin
拆分公共代碼 使用動態 import
,懶加載 React
組件
七、綁定this的幾種方式
bind/箭頭函數
複製代碼
八、對fiber的理解
React Fiber 是一種基於瀏覽器的單線程調度算法.
複製代碼
九、setState是同步仍是異步的
setState
只在合成事件和鉤子函數中是「異步」的,在原生事件和 setTimeout 中都是同步的。setState
的「異步」並非說內部由異步代碼實現,其實自己執行的過程和代碼都是同步的,只是合成事件和鉤子函數的調用順序在更新以前,致使在合成事件和鉤子函數中無法立馬拿到更新後的值,形式了所謂的「異步」,固然能夠經過第二個參數 setState(partialState, callback) 中的callback拿到更新後的結果。setState
的批量更新優化也是創建在「異步」(合成事件、鉤子函數)之上的,在原生事件和setTimeout 中不會批量更新,在「異步」中若是對同一個值進行屢次 setState , setState 的批量更新策略會對其進行覆蓋,取最後一次的執行,若是是同時 setState 多個不一樣的值,在更新時會對其進行合併批量更新。
十、Redux、React-Redux
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
和無狀態函數
1三、React
元素與組件的區別?
組件是由元素構成的。元素數據結構是普通對象,而組件數據結構是類或純函數。
Vue與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
)。
vuex 和 redux 之間的區別?
從實現原理上來講,最大的區別是兩點:
Redux使用的是不可變數據,而Vuex
的數據是可變的。Redux
每次都是用新的state
替換舊的state
,而Vuex
是直接修改
Redux在檢測數據變化的時候,是經過diff
的方式比較差別的,而Vuex
其實和Vue的原理同樣,是經過 getter/setter
來比較的(若是看Vuex
源碼會知道,其實他內部直接建立一個Vue
實例用來跟蹤數據變化)
瀏覽器從輸入url到渲染頁面,發生了什麼?
三個方面:
網絡篇:
構建請求
查找強緩存
DNS解析
創建TCP鏈接(三次握手)
發送HTTP請求(網絡請求後網絡響應)
瀏覽器解析篇:
解析html構建DOM樹
解析css構建CSS樹、樣式計算
生成佈局樹(Layout Tree)
瀏覽器渲染篇:
創建圖層樹(Layer Tree)
生成繪製列表
生成圖塊並柵格化
顯示器顯示內容
最後斷開鏈接:TCP 四次揮手
(瀏覽器會將各層的信息發送給GPU,GPU會將各層合成,顯示在屏幕上)
複製代碼
網絡安全、HTTP協議
TCP UDP 區別
1.`TCP`向上層提供面向鏈接的可靠服務 ,`UDP`向上層提供無鏈接不可靠服務。 2.雖然 `UDP` 並無 `TCP` 傳輸來的準確,可是也能在不少實時性要求高的地方有所做爲 3.對數據準確性要求高,速度能夠相對較慢的,能夠選用`TCP` 複製代碼
區別 | UDP | TCP |
---|---|---|
是否鏈接 | 無鏈接 | 面向鏈接 |
是否可靠 | 不可靠傳輸,不使用流量控制和擁塞控制 | 可靠傳輸,使用流量控制和擁塞控制 |
鏈接對象個數 | 支持一對一,一對多,多對一和多對多交互通訊 | 只能是一對一通訊 |
傳輸方式 | 面向報文 | 面向字節流 |
首部開銷 | 首部開銷小,僅8字節 | 首部最小20字節,最大60字節 |
適用場景 | 適用於實時應用(IP電話、視頻會議、直播等) | 適用於要求可靠傳輸的應用,例如文件傳輸 |
Http和Https區別(高頻)
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證書 複製代碼
GET和POST區別(高頻)
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,csrf,ddos攻擊原理以及避免方式
XSS
(Cross-Site Scripting
,跨站腳本攻擊)是一種代碼注入攻擊。攻擊者在目標網站上注入惡意代碼,當被攻擊者登錄網站時就會執行這些惡意代碼,這些腳本能夠讀取 cookie,session tokens
,或者其它敏感的網站信息,對用戶進行釣魚欺詐,甚至發起蠕蟲攻擊等。
CSRF
(Cross-site request forgery
)跨站請求僞造:攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站發送跨站請求。利用受害者在被攻擊網站已經獲取的註冊憑證,繞事後臺的用戶驗證,達到冒充用戶對被攻擊的網站執行某項操做的目的。
XSS避免方式:
url
參數使用encodeURIComponent
方法轉義- 儘可能不是有
InnerHtml
插入HTML
內容 - 使用特殊符號、標籤轉義符。
CSRF
避免方式:
- 添加驗證碼
- 使用token
- 服務端給用戶生成一個token,加密後傳遞給用戶
- 用戶在提交請求時,須要攜帶這個token
- 服務端驗證token是否正確
DDoS
又叫分佈式拒絕服務,全稱 Distributed Denial of Service
,其原理就是利用大量的請求形成資源過載,致使服務不可用。
DDos
避免方式:
- 限制單IP請求頻率。
- 防火牆等防禦設置禁止
ICMP
包等 - 檢查特權端口的開放
http特性以及狀態碼
好比: 200響應成功 301永久重定向 302臨時重定向 304資源緩存 403服務器禁止訪問 404服務器資源未找到 500 502服務器內部錯誤 504 服務器繁忙 1xx Informational(信息狀態碼) 接受請求正在處理 2xx Success(成功狀態碼) 請求正常處理完畢 3xx Redirection(重定向狀態碼) 須要附加操做已完成請求 4xx Client Error(客戶端錯誤狀態碼) 服務器沒法處理請求 5xx Server Error(服務器錯誤狀態碼) 服務器處理請求出錯 複製代碼
http三次握手
- 第一步:客戶端發送SYN報文到服務端發起握手,發送完以後客戶端處於SYN_Send狀態
- 第二步:服務端收到SYN報文以後回覆SYN和ACK報文給客戶端
- 第三步:客戶端收到SYN和ACK,向服務端發送一個ACK報文,客戶端轉爲established狀態,此時服務端收到ACK報文後也處於established狀態,此時雙方已創建了鏈接
http四次揮手
剛開始雙方都處於 establised
狀態,假如是客戶端先發起關閉請求,則:
- 第一次揮手:客戶端發送一個 FIN 報文,報文中會指定一個序列號。此時客戶端處於FIN_WAIT1狀態。
- 第二次揮手:服務端收到 FIN 以後,會發送 ACK 報文,且把客戶端的序列號值 + 1 做爲 ACK 報文的序列號值,代表已經收到客戶端的報文了,此時服務端處於 CLOSE_WAIT狀態。
- 第三次揮手:若是服務端也想斷開鏈接了,和客戶端的第一次揮手同樣,發給 FIN 報文,且指定一個序列號。此時服務端處於 LAST_ACK 的狀態。
- 第四次揮手:客戶端收到 FIN 以後,同樣發送一個 ACK 報文做爲應答,且把服務端的序列號值 + 1 做爲本身 ACK 報文的序列號值,此時客戶端處於 TIME_WAIT 狀態。須要過一陣子以確保服務端收到本身的 ACK 報文以後纔會進入 CLOSED 狀態
- 服務端收到 ACK 報文以後,就處於關閉鏈接了,處於 CLOSED 狀態。
http1.0、http1.一、http2.0的區別
- 1和1.0相比,1.1能夠一次傳輸多個文件
- http1.x解析基於文本,http2.0採用二進制格式,新增特性 多路複用、header壓縮、服務端推送(靜態html資源)
http如何實現緩存
- 強緩存==>Expires(過時時間)/Cache-Control(no-cache)(優先級高) 協商緩存 ==>Last-Modified/Etag(優先級高)Etag適用於常常改變的小文件 Last-Modefied適用於不怎麼常常改變的大文件
- 強緩存策略和協商緩存策略在緩存命中時都會直接使用本地的緩存副本,區別只在於協商緩存會向服務器發送一次請求。它們緩存不命中時,都會向服務器發送請求來獲取資源。在實際的緩存機制中,強緩存策略和協商緩存策略是一塊兒合做使用的。瀏覽器首先會根據請求的信息判斷,強緩存是否命中,若是命中則直接使用資源。若是不命中則根據頭信息向服務器發起請求,使用協商緩存,若是協商緩存命中的話,則服務器不返回資源,瀏覽器直接使用本地資源的副本,若是協商緩存不命中,則瀏覽器返回最新的資源給瀏覽器。
輸入url後http請求的完整過程
創建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
的方式,不經常使用。 - 平常工做中用的最對的跨域方案是CORS和Nginx反向代理
能不能說一說瀏覽器的本地存儲?各自優劣如何?
瀏覽器的本地存儲主要分爲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
: 也是在全部同源窗口中都是共享的.也就是說只要瀏覽器不關閉,數據仍然存在
前端工程化
webpack配置,webpack4.0有哪些優化點
module.exports={ entry: {}, output: {}, plugins: [], module: [rules:[{}]] } 複製代碼
webpack如何實現代碼分離
入口起點
:使用entry
配置手動地分離代碼。防止重複
:使用CommonsChunkPlugin
去重和分離chunk
。動態導入
:經過模塊的內聯函數調用來分離代碼。
常見的Webpack Loader? 如何實現一個Webpack Loader(NO)
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
代碼
常見的Webpack Plugin? 如何實現一個Webpack Plugin(NO)
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和plugin對比?
Loader
在module.rules
中配置,做爲模塊的解析規則,類型爲數組。每一項都是一個 Object
,內部包含了test(類型文件)、loader、options
(參數)等屬性。Plugin
在plugins
中單獨配置,類型爲數組,每一項是一個Plugin
的實例,參數都經過構造函數傳入。
前端模塊化,CMD、AMD、CommonJS
CommonJS
CommonJS
是服務器端模塊的規範,由Node推廣使用,webpack也採用這種規範編寫
commonJs規範:
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
AMD
是運行在瀏覽器環境的一個異步模塊定義規範 ,是RequireJS
在推廣過程當中對模塊定義的規範化產出。
AMD規範
AMD
推崇依賴前置,在定義模塊的時候就要聲明其依賴的模塊
優勢
用戶體驗好,由於沒有延遲,依賴模塊提早執行了。
CMD
CMD
是一個通用模塊定義規範;是SeaJs推廣過程當中對模塊定義的規範化產出
CMD規範
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); }, []); } 複製代碼
職業技能規劃、人事面試
- 將來準備往哪方面發展?精通/全乾
- 對於職業規劃的我的看法
- 自身價值的體現
離職緣由
- 我的職業規劃緣由
- 公司緣由
其餘
- 你將來一到三年的一個職業規劃是什麼?
- 你都是怎麼去學習和關注新技術的?
- 你近幾年工做中有哪些心得或總結?
- 你以爲你在工做中的優缺點是什麼?
- 你過來咱們公司,你的優點是什麼?
- 有些過開源項目嗎?
- 寫過 npm 包嗎,寫過 webpack 插件嗎?
- 看過哪些框架或者類庫的源碼,有什麼收穫?
補充
ES6裏的symble
它的功能相似於一種標識惟一性的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']
ES6裏的set和map
Map
對象保存鍵值對。任何值(對象或者原始值) 均可以做爲一個鍵或一個值。構造函數Map能夠接受一個數組做爲參數。Set
對象容許你存儲任何類型的值,不管是原始值或者是對象引用。它相似於數組,可是成員的值都是惟一的,沒有重複的值。
vue的key
key
的做用主要是爲了高效的更新虛擬DOM
,其原理是vue
在patch
過程當中經過key
能夠精準判斷兩個節點是不是同一個,
從而避免頻繁更新不一樣元素,使得整個patch
過程更加高效,減小DOM
操做量,提升性能。 2. 另外,若不設置key
還可能在列表更新時引起一些隱蔽的bug 3. vue
中在使用相同標籤名元素的過渡切換時,也會使用到key屬性,其目的也是爲了讓vue能夠區分它們, 不然vue
只會替換其內部屬性而不會觸發過渡效果。
普通函數和箭頭函數的區別
- 箭頭函數是匿名函數,不能做爲構造函數,不能使用new
- 箭頭函數不綁定
arguments
,取而代之用rest
參數...解決 - 箭頭函數不綁定
this
,會捕獲其所在的上下文的this值,做爲本身的this值 - 箭頭函數經過
call() 或 apply()
方法調用一個函數時,只傳入了一個參數,對 this 並無影響。 - 箭頭函數沒有原型屬性
- 箭頭函數不能當作
Generator
函數,不能使用yield
關鍵字
總結:
- 箭頭函數的
this
永遠指向其上下文的this
,任何方法都改變不了其指向,如call() , bind() , apply()
- 普通函數的this指向調用它的那個對象
JS函數柯里化
- 參數複用
- 提早確認
- 延遲運行
// 普通的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, mapGetters, mapActions, mapMutations
當一個組件須要獲取多個狀態時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。爲了解決這個問題,咱們可使用 mapState 輔助函數幫助咱們生成計算屬性 mapMutations 其實跟mapState 的做用是相似的,將組件中的 methods 映射爲 store.commit 調用
計算一個函數的難易程度公式
如上圖能夠粗略的分爲兩類,多項式量級和非多項式量級。其中,非多項式量級只有兩個:O(2n) 和 O(n!) 對應的增加率以下圖所示
vue源碼理解
xxxxx...
osi7層模型,tcp5層模型
osi7層模型:物理層-數據鏈路層-傳輸層-網絡層-應用層-會話層-表示層
tcp5層模型:物理層-數據鏈路層-傳輸層-網絡層-應用層
寫在最後
我是伊人a,與你相逢,我很開心。
-
文中若有錯誤,歡迎在評論區指正,若是這篇文章幫到了你,歡迎點贊👍和關注😊
-
本文首發於掘金,未經許可禁止轉載💌
面試思惟導圖(圖片太大建議下載查看)
結語
創做不易,若是對你們有所幫助,但願你們點贊支持,有什麼問題也能夠在評論區裏討論😄~