前端面經
HTML、CSS相關
HTML5新特性
input新增了一些屬性:color-調色盤、tel-電話、number-數字、date-年月日
video、aideo視音訊標籤
語義化標籤
語義化
語義化標籤 : header、nav、main、footer
語義化的優點有:
(一)程式碼結構清晰,易於閱讀,利於開發和維護
(二)方便裝置解析根據語義渲染網頁
(三)有利於(SEO)搜尋引擎優化
(四)在瀏覽器css失效時,頁面依然可讀
如何語義化:不用純樣式標籤(b、i、u)、少用無語義標籤(div、span)、使用語義化標籤
盒模型
所有HTML元素都可以看做是一個作盒子,在CSS中,"box model"
W3C盒子模型(標準盒子模型):寬=內部寬度(content)+border+padding+margin
IE盒子模型(怪異盒子模型):寬=內部寬度(content+border+padding)+margin
互換模型格式:
box-sizing:content-box;//變為標準盒模型(大部分瀏覽器預設)
box-sizing:border-box;//變為怪異盒子模型
行內元素、塊級元素、空元素有哪些?區別?
1、行內元素:span、a、em、img、input
2、塊級元素:div、ol、ul、form
3、空元素:br、hr、img、input
區別:
行內元素不換行、塊級元素換行
正常情況下是塊級元素包含行內元素,鮮少有行內元素包含塊級元素
沒有內容的標籤稱之為空元素,空元素是在開始標籤中關閉的。
離線快取與傳統瀏覽器快取的區別
離線快取是整個應用,傳統瀏覽器快取是單個檔案
離線快取斷網後依然可以開啟頁面,傳統瀏覽器快取不可以
離線緩斷在有網路情況下優先使用快取,傳統瀏覽器快取會通知網路更新快取
能不能說一說瀏覽器的本地儲存?各自優劣如何?
瀏覽器的本地儲存主要分為Cookie、WebStorage, 其中WebStorage又可以分為localStorage和sessionStorage。
共同點:都會在瀏覽器端儲存,有大小和同源限制
不同點:
一、cookie資料始終在同源的http請求中攜帶,即cookie在瀏覽器和伺服器間來回傳遞。sessionStorage和localStorage不會自動把資料傳送給伺服器,僅在本地儲存。
二、儲存大小限制也不同:cookie資料不能超過4K,sessionStorage和localStorage可以達到5M或者更多
三、作用域不同:sessionStorage:僅在當前瀏覽器視窗關閉之前有效;localstorage:資料始終有效,視窗或瀏覽器關閉也一直儲存,除非刪除資料;cookie:在設定的cookie過期時間之前有效,即使視窗關閉或瀏覽器關閉
CSS樣式優先順序
!important>style>id>class
BFC
BFC即塊格式化上下文。BFC內的元素不會影響外面的元素。
建立:
1.float不為none
2.position為absolute或fixed
3.overflow不為visible
4.display為inline-block、flex、inline-flex等
應用:
1.防止margin重疊
2.清除內部浮動
3.自適應多欄佈局
三欄佈局
絕對定位法:中間欄目使用margin/padding空出左右位置,左右使用絕對定位
浮動法:中間欄目使用margin/padding空出左右位置,左右使用浮動定位
Flex:flex:1
Grid:父元素:display:grid 子元素:grid-template-columns:100px auto 20px
CSS選擇器
標籤選擇器
ID選擇器
類選擇器
組選擇器
萬用字元選擇器
後代選擇器
子元素選擇器
偽類選擇器
Flex:1是什麼
經常用於自適應佈局。也就是flex-grow、flex-shrink、flex-basis的縮寫
Display:flex的常用屬性
flex-drection:設定主軸方向
Justify-content:設定主軸排列方式
Flex-wrap:設定是否換行
Align-content/align-item:側軸排列(多行/單行)
前處理器less、sass
是css中一種抽象層。好處:
1.結構清晰、便於擴充套件
2.方便遮蔽瀏覽器的語法差異
3.多重繼承
DOM、BOM物件
BOM是指瀏覽器物件模型,可以對瀏覽器視窗進行訪問和操作。使用 BOM,開發者可以移動視窗、改變狀態列中的文字以及執行其他與頁面內容不直接相關的動作。
DOM 是指文件物件模型,通過它,可以訪問HTML文件的所有元素。DOM是W3C的標準。
瀏覽器渲染機制
網頁生成過程:
1.HTML被HTML解析器解析成DOM樹
2.css則被css解析器解析成CSSOM樹
3.結合DOM樹和CSSOM樹,生成一棵渲染樹(Render Tree)
4.生成佈局(flow),即將所有渲染樹的所有節點進行平面合成
5.將佈局繪製(paint)在螢幕上
重排(也稱迴流)
當DOM的變化影響了元素的幾何資訊(DOM物件的位置和尺寸大小),瀏覽器需要重新計算元素的幾何屬性,將其安放在介面中的正確位置,這個過程叫做重排。 觸發:新增或者刪除可見的DOM元素、元素尺寸改變——邊距、填充、邊框、寬度和高度
重繪
當一個元素的外觀發生改變,但沒有改變佈局,重新把元素外觀繪製出來的過程,叫做重繪。 觸發:改變元素的color、background、box-shadow等屬性
重排重繪優化建議
1.樣式表越簡單,重排和重繪就越快。儘量用class,少用style一條條改變樣式
2.重排和重繪的DOM元素層級越高,成本就越高。如果可以靈活用display,absolute,flex等重排開銷會比較小,或不會影響其他元素的重排。
3.使用虛擬DOM的指令碼庫。
JS相關
js資料型別、typeof、instanceof
1)string、number、boolean、null、undefined、object(function、array)、symbol
2)typeof主要用來判斷資料型別
3)instanceof判斷該物件是誰的例項。
ES6
1.新增symbol型別 表示獨一無二的值,用來定義獨一無二的物件屬性名;
2.const/let 都是用來宣告變數,不可重複宣告,具有塊級作用域。存在暫時性死區,也就是不存在變數提升。(const一般用於宣告常量);
3.變數的解構賦值(包含陣列、物件、字串、數字及布林值,函式引數),剩餘運算子(...rest);
4.模板字串(${data});
5.擴充套件運算子(陣列、物件);;
6.箭頭函式;
7.Set和Map資料結構;
8.Proxy/Reflect;
9.Promise
ES6裡的symble
它的功能類似於一種標識唯一性的ID,每個Symbol例項都是唯一的。Symbol型別的key是不能通過Object.keys()或者for...in來列舉的, 它未被包含在物件自身的屬性名集合(property names)之中。 所以,利用該特性,我們可以把一些不需要對外操作和訪問的屬性使用Symbol來定義。
ES6裡的set和map
- Map物件儲存鍵值對。任何值(物件或者原始值) 都可以作為一個鍵或一個值。建構函式Map可以接受一個數組作為引數。
- Set物件允許你儲存任何型別的值,無論是原始值或者是物件引用。它類似於陣列,但是成員的值都是唯一的,沒有重複的值。
vue的key
1.key的作用主要是為了高效的更新虛擬DOM,其原理是vue在patch過程中通過key可以精準判斷兩個節點是否是同一個,從而避免頻繁更新不同元素,使得整個patch過程更加高效,減少DOM操作量,提高效能。
2.另外,若不設定key還可能在列表更新時引發一些隱蔽的bug
3.vue中在使用相同標籤名元素的過渡切換時,也會使用到key屬性,其目的也是為了讓vue可以區分它們, 否則vue只會替換其內部屬性而不會觸發過渡效果。
普通函式和箭頭函式的區別
1.箭頭函式是匿名函式,不能作為建構函式,不能使用new
2.箭頭函式不繫結arguments,取而代之用rest引數...解決
3.箭頭函式不繫結this,會捕獲其所在的上下文的this值,作為自己的this值
4.箭頭函式通過call() 或 apply()方法呼叫一個函式時,只傳入了一個引數,對 this 並沒有影響。
5.箭頭函式不能當做Generator函式,不能使用yield關鍵字
閉包(高頻)
閉包是指有權訪問另一個函式作用域中的變數的函式 當函式可以記住並訪問所在的詞法作用域時,就產生了閉包,即使函式是在當前詞法作用域之外執行
- 閉包用途:
能夠訪問函式定義時所在的詞法作用域(阻止其被回收)
私有化變數
模擬塊級作用域
建立模組
- 閉包缺點:會導致函式的變數一直儲存在記憶體中,過多的閉包可能會導致記憶體洩漏
原型、原型鏈(高頻)
原型:物件中固有的__proto__屬性,該屬性指向物件的prototype原型屬性。
原型鏈:當我們訪問一個物件的屬性時,如果這個物件內部不存在這個屬性,那麼它就會去它的原型物件裡找這個屬性,這個原型物件又會有自己的原型,於是就這樣一直找下去,也就是原型鏈的概念。原型鏈的盡頭一般來說都是Object.prototype所以這就是我們新建的物件為什麼能夠使用toString()等方法的原因。
特點:JavaScript物件是通過引用來傳遞的,我們建立的每個新物件實體中並沒有一份屬於自己的原型副本。當我們修改原型時,與之相關的物件也會繼承這一改變。
this指向
代表的是當前上下文環境物件。在面嚮物件語言中this表示當前物件的一個引用。但在JavaScript中this是不固定的,它會隨著環境的改變而改變。
1)在方法中,this表示該方法所屬的物件
2)在單獨使用的情況下,this代表的是全域性物件
3)在函式中,this表示的是全域性物件
4)在函式中但是在嚴格模式下,this為未定義(undefined)
5)在事件中,this表示的是接收事件的元素
類似call、apply等方法可以改變this引用到的物件apply 、 call 和 bind呼叫模式,這三個方法都可以顯示的指定呼叫函式的 this 指向。apply接收引數的是陣列,call接受引數列表,bind方法傳入一個物件。
new關鍵字
1.首先建立了一個新的空物件
2.設定原型,將物件的原型設定為函式的prototype物件。
3.讓函式的this指向這個物件,執行建構函式的程式碼(為這個新物件新增屬性)
4.判斷函式的返回值型別,如果是值型別,返回建立的物件。如果是引用型別,就返回這個引用型別的物件。
作用域、作用域鏈
作用域負責收集和維護由所有宣告的識別符號(變數)組成的一系列查詢,並實施一套非常嚴格的規則,確定當前執行的程式碼對這些識別符號的訪問許可權。(全域性作用域、函式作用域、塊級作用域)。 作用域鏈就是從當前作用域開始一層一層向上尋找某個變數,直到找到全域性作用域還是沒找到,就宣佈放棄。這種一層一層的關係,就是作用域鏈。
繼承(含es6)、多種繼承方式
(1)第一種是以原型鏈的方式來實現繼承,但是這種實現方式存在的缺點是,在包含有引用型別的資料時,會被所有的例項物件所共享,容易造成修改的混亂。還有就是在建立子型別的時候不能向超型別傳遞引數。
(2)第二種方式是使用借用建構函式的方式,這種方式是通過在子型別的函式中呼叫超型別的建構函式來實現的,這一種方法解決了不能向超型別傳遞引數的缺點,但是它存在的一個問題就是無法實現函式方法的複用,並且超型別原型定義的方法子型別也沒有辦法訪問到。
(3)第三種方式是組合繼承,組合繼承是將原型鏈和借用建構函式組合起來使用的一種方式。通過借用建構函式的方式來實現型別的屬性的繼承,通過將子型別的原型設定為超型別的例項來實現方法的繼承。這種方式解決了上面的兩種模式單獨使用時的問題,但是由於我們是以超型別的例項來作為子型別的原型,所以呼叫了兩次超類的建構函式,造成了子型別的原型中多了很多不必要的屬性。
(4)第四種方式是原型式繼承,原型式繼承的主要思路就是基於已有的物件來建立新的物件,實現的原理是,向函式中傳入一個物件,然後返回一個以這個物件為原型的物件。這種繼承的思路主要不是為了實現創造一種新的型別,只是對某個物件實現一種簡單繼承,ES5 中定義的 Object.create() 方法就是原型式繼承的實現。缺點與原型鏈方式相同。
(5)第五種方式是寄生式繼承,寄生式繼承的思路是建立一個用於封裝繼承過程的函式,通過傳入一個物件,然後複製一個物件的副本,然後物件進行擴充套件,最後返回這個物件。這個擴充套件的過程就可以理解是一種繼承。這種繼承的優點就是對一個簡單物件實現繼承,如果這個物件不是我們的自定義型別時。缺點是沒有辦法實現函式的複用。
(6)第六種方式是寄生式組合繼承,組合繼承的缺點就是使用超型別的例項做為子型別的原型,導致添加了不必要的原型屬性。寄生式組合繼承的方式是使用超型別的原型的副本來作為子型別的原型,這樣就避免了建立不必要的屬性。
EventLoop
JS是單執行緒的,為了防止一個函式執行時間過長阻塞後面的程式碼,所以會先將同步程式碼壓入執行棧中,依次執行,將非同步程式碼推入非同步佇列,非同步佇列又分為巨集任務佇列和微任務佇列,因為巨集任務佇列的執行時間較長,所以微任務佇列要優先於巨集任務佇列。微任務佇列的代表就是,Promise.then,MutationObserver,巨集任務的話就是setImmediate setTimeout setInterval
原生ajax
ajax是一種非同步通訊的方法,從服務端獲取資料,達到區域性重新整理頁面的效果。 過程:
1.建立XMLHttpRequest物件;
2.呼叫open方法傳入三個引數 請求方式(GET/POST)、url、同步非同步(true/false);
3.監聽onreadystatechange事件,當readystate等於4時返回responseText;
4.呼叫send方法傳遞引數。
事件冒泡、捕獲(委託)
- 事件冒泡指在在一個物件上觸發某類事件,如果此物件綁定了事件,就會觸發事件,如果沒有,就會向這個物件的父級物件傳播,最終父級物件觸發了事件。
- 事件委託本質上是利用了瀏覽器事件冒泡的機制。因為事件在冒泡過程中會上傳到父節點,並且父節點可以通過事件物件獲取到目標節點,因此可以把子節點的監聽函式定義在父節點上,由父節點的監聽函式統一處理多個子元素的事件,這種方式稱為事件代理。
event.stopPropagation()或者 ie下的方法event.cancelBubble = true;//阻止事件冒泡
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: 此時可以操作Dom
- update階段:當vue例項裡面的data資料變化時,觸發元件的重新渲染beforeUpdateupdated
- destroy階段:vue例項被銷燬beforeDestroy:例項被銷燬前,此時可以手動銷燬一些方法destroyed
data為什麼是一個函式而不是物件
因為物件是一個引用資料型別,如果data是一個物件的情況下會造成所有元件共用一個data。而當data是一個函式的情況下,每次函式執行完畢後都會返回一個新的物件,這樣的話每個元件都會維護一份獨立的物件(data)
computed與watch
watch 屬性監聽是一個物件,鍵是需要觀察的屬性,值是對應回撥函式,主要用來監聽某些特定資料的變化,從而進行某些具體的業務邏輯操作,監聽屬性的變化,需要在資料變化時執行非同步或開銷較大的操作時使用
computed 計算屬性屬性的結果會被快取,當computed中的函式所依賴的屬性沒有發生改變的時候,那麼呼叫當前函式的時候結果會從快取中讀取。除非依賴的響應式屬性變化時才會重新計算,主要當做屬性來使用computed中的函式必須用return返回最終的結果computed更高效,優先使用
使用場景computed:當一個屬性受多個屬性影響的時候使用,例:購物車商品結算功能watch:當一條資料影響多條資料的時候使用,例:搜尋資料
v-for中key的作用
1.key的作用主要是為了更高效的對比虛擬DOM中每個節點是否是相同節點;
2.Vue在patch過程中判斷兩個節點是否是相同節點,key是一個必要條件,渲染一組列表時,key往往是唯一標識,所以如果不定義key的話,Vue只能認為比較的兩個節點是同一個,哪怕它們實際上不是,這導致了頻繁更新元素,使得整個patch過程比較低效,影響效能;
3.從原始碼中可以知道,Vue判斷兩個節點是否相同時主要判斷兩者的key和元素型別等,因此如果不設定key,它的值就是undefined,則可能永 遠認為這是兩個相同的節點,只能去做更新操作,這造成了大量的dom更新操作,明顯是不可取的。
vue元件的通訊方式
父子元件通訊
父->子props,子->父$on、$emit` 獲取父子元件例項parent、parent、childrenRef獲取例項的方式呼叫元件的屬性或者方法Provide、inject` 官方不推薦使用,但是寫元件庫時很常用
兄弟元件通訊
Event Bus實現跨元件通訊Vue.prototype.$bus = new Vue() Vuex
跨級元件通訊
$attrs、$listenersProvide、inject
路由傳參
1.使用router-link進行路由導航,傳遞引數
2.直接呼叫$router.push 實現攜帶引數的跳轉
3.通過路由屬性中的name來確定匹配的路由,通過params來傳遞引數
4.使用path來匹配路由,然後通過query來傳遞引數,這種情況下 query傳遞的引數會顯示在url
路由的兩種模式 hash與history
對於Vue 這類漸進式前端開發框架,為了構建SPA(單頁面應用),需要引入前端路由系統,這也就是Vue-router存在的意義。前端路由的核心,就在於改變檢視的同時不會向後端發出請求。
1、hash ——即位址列URL中的#符號,它的特點在於:hash 雖然出現URL中,但不會被包含在HTTP請求中,對後端完全沒有影響,因此改變hash不會重新載入頁面。
2、history ——利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法。這兩個方法應用於瀏覽器的歷史記錄站,在當前已有的back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改是,雖然改變了當前的URL,但你瀏覽器不會立即向後端傳送請求。history模式,會出現404 的情況,需要後臺配置。
路由守衛
雙向繫結實現原理
當一個Vue例項建立時,Vue會遍歷data選項的屬性,用Object.defineProperty將它們轉為 getter/setter並且在內部追蹤相關依賴,在屬性被訪問和修改時通知變化。每個元件例項都有相應的 watcher 程式例項,它會在元件渲染的過程中把屬性記錄為依賴,之後當依賴項的 setter 被呼叫時,會通知 watcher重新計算,從而致使它關聯的元件得以更新。
v-model的實現以及它的實現原理嗎?
1.vue中雙向繫結是一個指令v-model,可以繫結一個動態值到檢視,同時檢視中變化能改變該值。v-model是語法糖,預設情況下相於:value和@input。
2.使用v-model可以減少大量繁瑣的事件處理程式碼,提高開發效率,程式碼可讀性也更好
3.通常在表單項上使用v-model
4.原生的表單項可以直接使用v-model,自定義元件上如果要使用它需要在元件內繫結value並處理輸入事件
5.我做過測試,輸出包含v-model模板的元件渲染函式,發現它會被轉換為value屬性的繫結以及一個事件監聽,事件回撥函式中會做相應變數更新操作,這說明神奇魔法實際上是vue的編譯器完成的。
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:提供資料注入。
思考:為什麼先注入再提供呢??
1、首先來自祖輩的資料要和當前例項的data,等判重,相結合,所以注入資料的initInjections一定要在InitState的上面。
2. 從上面注入進來的東西在當前元件中轉了一下又提供給後代了,所以注入資料也一定要在上面。
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 Vnodeold 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至少有一個已經遍歷完了,就會結束比較。
瀏覽器從輸入url到渲染頁面,發生了什麼?
三個方面:
網路篇:
1.構建請求
2.查詢強快取
3.DNS解析
4.建立TCP連線(三次握手)
5.傳送HTTP請求(網路請求後網路響應)
瀏覽器解析篇:
1.解析html構建DOM樹
2.解析css構建CSS樹、樣式計算
3.生成佈局樹(Layout Tree)
瀏覽器渲染篇:
1.建立圖層樹(Layer Tree)
2.生成繪製列表
3.生成圖塊並柵格化
4.顯示器顯示內容
5.最後斷開連線:TCP 四次揮手
Http和Https區別(高頻)
1.`HTTP`是不安全的,而 HTTPS 是安全的
2.`HTTP`標準埠是80,而 HTTPS 的標準埠是443
3.`HTTP`無法加密,而HTTPS 對傳輸的資料進行加密
4.`HTTP`無需證書,而HTTPS 需要CA的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避免方式:
1.url引數使用encodeURIComponent方法轉義
2.儘量不是有InnerHtml插入HTML內容
3.使用特殊符號、標籤轉義符。
CSRF避免方式:
1.新增驗證碼
2.使用token
服務端給使用者生成一個token,加密後傳遞給使用者
使用者在提交請求時,需要攜帶這個token
服務端驗證token是否正確
http特性以及狀態碼
比如:
200響應成功
301永久重定向
302臨時重定向
304資源快取
403伺服器禁止訪問
404伺服器資源未找到
500502伺服器內部錯誤
504伺服器繁忙
1xx Informational(資訊狀態碼) 接受請求正在處理
2xx Success(成功狀態碼) 請求正常處理完畢
3xx Redirection(重定向狀態碼) 需要附加操作已完成請求
4xx Client Error(客戶端錯誤狀態碼) 伺服器無法處理請求
5xx Server Error(伺服器錯誤狀態碼) 伺服器處理請求出錯複製程式碼
http如何實現快取
1.強快取==>Expires(過期時間)/Cache-Control(no-cache)(優先順序高) 協商快取 ==>Last-Modified/Etag(優先順序高)Etag適用於經常改變的小檔案 Last-Modefied適用於不怎麼經常改變的大檔案
2.強快取策略和協商快取策略在快取命中時都會直接使用本地的快取副本,區別只在於協商快取會向伺服器傳送一次請求。它們快取不命中時,都會向伺服器傳送請求來獲取資源。在實際的快取機制中,強快取策略和協商快取策略是一起合作使用的。瀏覽器首先會根據請求的資訊判斷,強快取是否命中,如果命中則直接使用資源。如果不命中則根據頭資訊向伺服器發起請求,使用協商快取,如果協商快取命中的話,則伺服器不返回資源,瀏覽器直接使用本地資源的副本,如果協商快取不命中,則瀏覽器返回最新的資源給瀏覽器。
什麼是同源策略
一個域下的js指令碼未經允許的情況下,不能訪問另一個域下的內容。通常判斷跨域的依據是協議、域名、埠號是否相同,不同則跨域。同源策略是對js指令碼的一種限制,並不是對瀏覽器的限制,像img,script指令碼請求不會有跨域限制。
前後端如何通訊
Ajax : 短連線
Websocket : 長連線,雙向的。
Form表單:最原始的
跨域通訊的幾種方式
解決方案:
1.jsonp(利用script標籤沒有跨域限制的漏洞實現。缺點:只支援GET請求)
2.CORS(設定Access-Control-Allow-Origin:指定可訪問資源的域名)
3.postMessage(message, targetOrigin, [transfer])(HTML5新增API 用於多視窗訊息、頁面內嵌iframe訊息傳遞),通過onmessage監聽 傳遞過來的資料
4.Websocket是HTML5的一個持久化的協議,它實現了瀏覽器與伺服器的全雙工通訊,同時也是跨域的一種解決方案。
5.Node中介軟體代理
6.Nginx反向代理
7.各種巢狀iframe的方式,不常用。
8.日常工作中用的最對的跨域方案是CORS和Nginx反向代理
前端工程化
webpack配置,webpack4.0有哪些優化點
module.exports={
entry: {},
output: {},
plugins: [],
module: [rules:[{}]]
}
webpack如何實現程式碼分離
1.入口起點:使用entry配置手動地分離程式碼。
2.防止重複:使用CommonsChunkPlugin去重和分離chunk。
3.動態匯入:通過模組的行內函數呼叫來分離程式碼。
常見的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); }, []); }
你都做過哪些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壓縮等。
寫的比較匆忙,可能有諸多問題,望各位大佬指正。