前端面試題收集整理ಠᴗಠ 查漏補缺刷一波

目錄

  1. 閉包
  2. jwt-token的優缺點
  3. vue的生命週期
  4. vue數據雙向綁定的底層實現
  5. 回調函數,Promise,async/await三者的區別
  6. Vue-Router模式
  7. 前端測試和web壓力測試
  8. XSS和CSRF以及如何防範
  9. SPA如何計算PV
  10. js domlist如何轉array
  11. generator函數和async函數的區別
  12. css3圓型頭像
  13. 排序的幾種方法
  14. 哈希如何解決衝突
  15. 如何保存路由信息呢,比如刷新?
  16. 如何實現一個文本和一個輸入框的兩端對齊

1. 閉包

自由變量和作用域和閉包 ლ(´ڡ`ლ)

2. jwt-token的優缺點

JWT的優點:

  • 體積小,因而傳輸速度更快
  • 多樣化的傳輸方式,可以通過URL傳輸、POST傳輸、請求頭Header傳輸(常用)
  • 簡單方便,服務端拿到jwt後無需再次查詢數據庫校驗token可用性,也無需進行redis緩存校驗
  • 在分佈式系統中,很好地解決了單點登錄問題
  • 很方便的解決了跨域授權問題,因爲跨域無法共享cookie

JWT的缺點:

  • 因爲JWT是無狀態的,因此服務端無法控制已經生成的Token失效,這是不可控的
  • 獲取到JWT也就擁有了登錄權限,因此JWT是不可泄露的,網站最好使用https,防止中間攻擊偷取JWT

實現登錄狀態保持的方法:cookie session token jwt

3. vue的生命週期

每個vue實例在被創建之前,都要經過一系列的初始化過程,這個過程就是vue的生命週期。

vue整個生命週期中的鉤子函數如下:

鉤子函數 組件狀態 最佳實踐
beforeCreate 實例初始化之後,this指向創建的實例,不能訪問到data,computed,watch,methods上的方法和數據 常用於初始化非響應式變量
created 實例創建完成,可訪問data,computed,watch,methods上的方法和數據,未掛載到DOM,不能訪問到el屬性,ref屬性內容爲空數組 常用於簡單的ajax請求,頁面的初始化
beforeMount 在掛載開始之前被調用,beforeMount之前,會找到對應的template,並編譯成render函數
mounted 實例掛載在DOM上,此時可以通過DOM API獲取到DOM節點,$ref屬性可以訪問 常用於獲取VNode信息和操作,ajax請求
beforeupdate 響應式數據更新時調用,發生在虛擬DOM打補丁之前 適合在更新之前訪問現有的DOM,比如手動移除已添加的事件監聽器
updated 虛擬DOM重新渲染和打補丁之後調用,組件DOM已經更新,可執行依賴於DOM的操作 避免在這個鉤子函數中操作數據,可能陷入死循環
beforeDestroy 實例銷燬之前調用。這一步,實例仍然完全可用,this仍能獲取到實例 常用於銷燬定時器,解綁全局事件,銷燬插件對象等操作
destroyed 實例銷燬後調用,調用後,Vue實例指示的所有東西都會解綁,所有的事件監聽器會被移除,所有的子實例也會被銷燬

注意:

  • created階段的ajax請求與mounted請求的區別:前者頁面視圖未出現,如果請求信息過多,頁面會長時間處於白屏狀態
  • mounted不會承諾所有的子組件也都一起被掛載。如果你希望等到整個視圖都渲染完畢,可以用 vm.$nextTick
  • vue2.0之後主動調用$destroy()不會移除dom節點,作者不推薦直接destroy這種做法,如果實在需要這樣用可以在這個生命週期鉤子中手動移除dom節點

4. vue數據雙向綁定的底層實現

vue實現數據雙向綁定主要是:採用 數據劫持結合發佈者-訂閱者模式的方式,通過 Object.defineProperty()來劫持各個屬性的settergetter,在數據變動時發佈消息給訂閱者,觸發相應監聽回調。當把一個普通 Javascript對象傳給 Vue 實例來作爲它的 data 選項時,Vue將遍歷它的屬性,用 Object.defineProperty()將它們轉爲getter/setter。用戶看不到 getter/setter,但是在內部它們讓 Vue 追蹤依賴,在屬性被訪問和修改時通知變化。

vue的數據雙向綁定 將MVVM作爲數據綁定的入口,整合ObserverCompileWatcher三者,通過Observer來監聽自己的model的數據變化,通過Compile來解析編譯模板指令(vue中是用來解析 {{}}),最終利用watcher搭起observerCompile之間的通信橋樑,達到數據變化 —>視圖更新;視圖交互變化(input)—>數據model變更雙向綁定效果。

5. 回調函數,Promise,async/await三者的區別

傳統的回調函數
當一個函數需要依賴上一個回調函數的值的時候,就會形成回調函數嵌套(如setTimeout,ajax等)
傳統的回調函數處理方式會產生“回調地獄”,代碼橫向發展

setTimeout(function () {
    //do something
    setTimeout(function () {
        //do something
        setTimeout(function () {
            //do something
            setTimeout(function () {
                 //do something
            }, 1000)
        }, 1000)
    }, 1000)
}, 1000)

Promise
Promise(ES2015) 是異步編程的一種解決方案,其實是一個構造函數,自己身上有all、reject、resolve這幾個方法,原型上有then、catch等方法。

如下,鏈式操作,代碼縱向發展

let p = new Promise(function(resolve,reject){
    resolve(1)
})
p.then(function(value){
    console.log(value)  // 1
    return value*2
}).then(function(value){
    console.log(value)  // 2
}).then(function(value){
    console.log(value)  // undefined
    return Promise.resolve('resolve')
}).then(function(value){
    console.log(value)  // resolve
    return Promise.reject('reject')
}).then(function(value){
    console.log(value)
},function(err){
    console.log(err) // reject
})

async/await
儘管Promise解決了地獄回調問題,但是還是不夠簡潔,一個是橫向發展,一個是縱向發展。
所以ES2017增加了異步函數,async/await使代碼看起來像是同步的,但它在後臺是異步和非阻塞的。

async是一個修飾符,async定義的函數會默認的返回一個Promise對象resolve的值,因此對async函數可以直接進行then操作,返回的值即爲then方法的傳入函數

async function funa() {
    console.log('a')
    return 'a'
}
funa().then( x => { console.log(x) })  //  輸出: a a
async function funp() {
    console.log('Promise')
    return new Promise(function(resolve, reject){
        resolve('Promise')
    })
}
funp().then( x => { console.log(x) })   // 輸出: Promise  Promise

await也是一個修飾符,
await 關鍵字 只能放在 async函數內部, await關鍵字的作用 就是獲取 Promise中返回的內容, 獲取的是Promise函數中resolve或者reject的值
如果await後面並不是一個Promise的返回值,則會按照同步程序返回值處理

const text1 = () => {
    return new Promise(resolve => {
        setTimeout(() => resolve('I did something'), 10000)
    })
}
const text2 = async () => {
    const something = await text1()
    return something + ' and I watched'
}
const text3 = async () => {
    const something = await text2()
    const s = await '啊'
    return something + ' and I watched as well'+ s
}
text3().then((res) => {
    console.log(res)   //I did something and I watched and I watched as well啊
})

6. Vue-Router模式

vue-router中的模式選項主要在router實例化的時候定義:
示例代碼:

export default new Router({
  mode: 'history', // 兩種類型:history 或者 hash
  routes
})
模式 優點 缺點
hash 使用簡單,無需後臺支持 在url中以hash形式存在,不會傳到後臺
history 地址明確,便於理解和後臺處理 需要後臺配合
  • vue-router 默認 hash 模式 ;
    例如:http://yoursite.com/#/index,hash值爲#/indexhash模式的特點在於hash出現在url中,但是不會被包括在HTTP請求中,對後端沒有影響,不會重新加載頁面。
  • 當你使用 history 模式時,URL 就像正常的 url,例如 http://yoursite.com/user/id,相比hash模式更加好看
  • 不過這種模式要玩好,還需要後臺配置支持。因爲我們的應用是個單頁客戶端應用,如果後臺沒有正確的配置,當用戶在瀏覽器直接訪問 http://oursite.com/user/id 就會返回 404,這就不好看了。
  • 所以呢,你要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app依賴的頁面。

7. 前端測試和web壓力測試

這方面還沒涉及到,好像是使用很多測試工具的樣子,容我緩緩,後續補上。。。

8. XSS和CSRF以及如何防範

XSS,CSRF,SQL注入

9. SPA如何計算PV

單頁面應用 SPA(Single Page Application)
概念: Web應用即使不刷新也在不同的頁面間切換,解決瀏覽器前進,後退等機制被破壞等問題
實現方法:

  • Node+Html5實現
  • React/VueMVVM框架

頁面訪問量 PV(PageView)

那麼,SPA如何計算PV?
利用 Page VisibilityHistory API來準確統計 Page View的基本思路如下(這種思路適用於傳統網站、SPAPWA):

  1. 頁面加載時,如果頁面的visibilityState 是可見的,發送 Page View統計;
  2. 如果頁面的 visibilityState 是隱藏的,就監聽 visibilitychange 事件,並在 visibilityState 變爲可見時發送 Page View 統計;
  3. 如果 visibilityState 由隱藏變爲可見,並且自上次用戶交互之後已經過了“足夠長”的時間,就發送新的Page View統計;
  4. 如果 URL 發生變化(僅限於 pathnamesearch 部分發送變化, hash 部分則應該忽略,因爲它是用來標記頁面內跳轉的) 發送新的Page View統計;

以上內容來源自:爲什麼你統計 PV 的方式是錯的?感興趣的可以看看

總結: 統計PV,可以自己寫腳本,可以用別人寫的腳本,也可以使用一些平臺的API(如:百度統計開放平臺等)

10. js domlist如何轉array

<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
var allP = document.querySelectorAll('p')
console.log(allP)
console.log([...allP])

控制檯輸出如下:
在這裏插入圖片描述
我們可以使用擴展運算符將NodeList對象轉換爲數組:
形式如下:[...document.querySelectorAll('p')]
注意: 擴展運算符實際上調用的是遍歷器接口,如果一個對象沒有部署此接口就無法完成轉換
JS解構和 … 運算符

11. generator函數和async函數的區別

  • async 函數只能用來處理Promise,而generator則可以處理任何函數
  • async 函數返回Promisegenerator返回{ value, done }類型的對象
  • generator屬於一種生成器,用來生成Iterator對象,在配合co的時候能用來解決異步
  • async則是爲了更簡潔的使用Promise而提出的語法,專門爲了解決異步而提出

12. css3圓型頭像

如果圖片是正方形,直接設置圖片的寬高和border-radius

<img src="img/favicon.png" alt="">
img{
	width:50px;
	height: 50px;
	border-radius: 25px;
}

在這裏插入圖片描述
如果圖片不是正方形,可以使用CSS背景圖片來顯示

<div class="img"></div>
.img{
	width:50px;
	height: 50px;
	border-radius: 25px;
	background: url("img/img78.jpg") no-repeat center;
	background-size:50px;
}

在這裏插入圖片描述
background相關屬性,自行百度

13. 排序的幾種方法

JS排序算法

14. 哈希如何解決衝突

在這裏插入圖片描述
誒呦我去,後續補上,感興趣的自行百度!

15. 如何保存路由信息呢,比如刷新?

問題: Vue單頁面應用中,在某個具體頁面下點擊刷新,那麼刷新後,頁面的狀態信息可能就會丟失掉
解決辦法: 監聽頁面的加載和刷新;頁面加載時,讀取sessionStorage裏的狀態信息到vuex;頁面刷新時,讀取vuex裏的信息保存到sessionStorage;
App.vuecreated鉤子函數裏寫:

 created () {
    //在頁面加載時讀取sessionStorage裏的狀態信息
    if (sessionStorage.getItem("store") ) {
      this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("store"))))
    }

    //在頁面刷新時將vuex裏的信息保存到sessionStorage裏
    window.addEventListener("beforeunload",()=>{
      sessionStorage.setItem("store",JSON.stringify(this.$store.state))
    })
  }

16. 如何實現一個文本和一個輸入框的兩端對齊

在這裏插入圖片描述
可以添加兩個空格轉義符&nbap;來到達此效果

label{
	display: inline-block;
	width:50px;
}
<form action="">
	<label for="username">用戶名</label>
	<input type="text" id="username">
	<br/>
	<label for="password">&nbsp;&nbsp;&nbsp;</label>
	<input type="password" id="password">
</form>

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章