面試總結
-
重視基礎和原理
-
重視基礎和原理
-
重視基礎和原理
一面
- 原型
構造函數 ,是一種特殊的方法。主要用來在創建對象時初始化對象。每個構造函數都有prototype(原型)屬性
每個函數都有prototype(原型)屬性,這個屬性是一個指針,指向一個對象,
這個對象的用途是包含特定類型的所有實例共享的屬性和方法,即這個原型對象是用來給實例共享屬性和方法的。
而每個實例內部都有一個指向原型對象的指針。
- 閉包
簡單來說就是函數嵌套函數,內部函數引用來外部函數的變量,從而導致來垃圾回收機制沒有生效,變量被保存來下來。
也就是所謂的內存泄漏,然后由於內存泄漏又會導致你項目逐漸變得卡頓等等問題。因此要避免內存泄漏。
- 原型鏈
提到原型鏈就不得不提原型的繼承,繼承的完美實現方案是借助寄生組合繼承,主要實現原理
PersonB.prototype = Object.create(PersonA.prototype)實現來繼承PersonA的原型
當我們通過new關鍵字實例化的對象身上就有了PersonB自身的屬性和方法,也有了PersonA的原型方法
當實例化對象調用某個方法時會先在自身和原型上查找,然后是在_proto_上一層層查找,這種方式就是原型鏈。
- vuex
Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態
並以相應的規則保證狀態以一種可預測的方式發生變化。
tate:Vuex 使用單一狀態樹——是的,用一個對象就包含了全部的應用層級狀態。
mutation:更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation
action: action 提交的是 mutation,而不是直接變更狀態。action 可以包含任意異步操作。
getter: 相當於Vue中的computed計算屬性
- vue-router
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構建單頁面應用變得易如反掌
<router-link>和<router-view>和<keep-alive>
- 深拷貝淺拷貝
深拷貝:
通過利用JSON.parse(JSON.stringify(Object))來達到深拷貝的目的
但是JSON深拷貝的缺點是undefined和function還有symbol類型是無法進行深拷貝的
如有需要可以自己手動封裝函數來達到目的
淺拷貝:
通過ES6新特性Object.assign()與擴展運算符來達到淺拷貝的目的
- Vue通信
第一種:props和$emit
第二種:中央事件總線 EventBus(基本不用)
第三種:vuex(狀態管理器)
第四種:$parent 和 $children
當然還有其他辦法,但是基本不常用
- 你在工作中遇到那些問題,解決方法是什么
經常遇到的問題就是Cannot read property ‘prototype’ of undefined
解決辦法通過瀏覽器報錯提示代碼定位問題,解決問題
Vue項目中遇到視圖不更新,方法不執行,埋點不觸發等問題
一般解決方案查看瀏覽器報錯,查看代碼運行到那個階段未之行結束,閱讀源碼以及相關文檔等
然后舉出來最近開發的項目中遇到的算是兩個比較大的問題。
- webpack配置入口出口
module.exports={
//入口文件的配置項
entry:{},
//出口文件的配置項
output:{},
//模塊:例如解讀CSS,圖片如何轉換,壓縮
module:{},
//插件,用於生產模版和各項功能
plugins:[],
//配置webpack開發服務功能
devServer:{}
}
簡單描述了一下這幾個屬性是干什么的。
- webpack3和webpack4區別
1.mode
webpack增加了一個mode配置,只有兩種值development | production。對不同的環境他會啟用不同的配置。
2.CommonsChunkPlugin
CommonChunksPlugin已經從webpack4中移除。
可使用optimization.splitChunks進行模塊划分(提取公用代碼)。
但是需要注意一個問題,默認配置只會對異步請求的模塊進行提取拆分,如果要對entry進行拆分
需要設置optimization.splitChunks.chunks = 'all'。
3.webpack4使用MiniCssExtractPlugin取代ExtractTextWebpackPlugin。
4.代碼分割。
使用動態import,而不是用system.import或者require.ensure
5.vue-loader。
使用vue-loader插件為.vue文件中的各部分使用相對應的loader,比如css-loader等
6.UglifyJsPlugin
現在也不需要使用這個plugin了,只需要使用optimization.minimize為true就行,production mode下面自動為true
optimization.minimizer可以配置你自己的壓縮程序
二面
- 陳述輸入URL回車后的過程
1.讀取緩存:
搜索自身的 DNS 緩存。(如果 DNS 緩存中找到IP 地址就跳過了接下來查找 IP 地址步驟,直接訪問該 IP 地址。)
2.DNS 解析:將域名解析成 IP 地址
3.TCP 連接:TCP 三次握手,簡易描述三次握手
客戶端:服務端你在么?
服務端:客戶端我在,你要連接我么?
客戶端:是的服務端,我要鏈接。
連接打通,可以開始請求來
4.發送 HTTP 請求
5.服務器處理請求並返回 HTTP 報文
6.瀏覽器解析渲染頁面
7.斷開連接:TCP 四次揮手
關於第六步瀏覽器解析渲染頁面又可以聊聊如果返回的是html頁面
根據 HTML 解析出 DOM 樹
根據 CSS 解析生成 CSS 規則樹
結合 DOM 樹和 CSS 規則樹,生成渲染樹
根據渲染樹計算每一個節點的信息
根據計算好的信息繪制頁面
- 陳述http
基本概念:
HTTP,全稱為 HyperText Transfer Protocol,即為超文本傳輸協議。是互聯網應用最為廣泛的一種網絡協議
所有的 www 文件都必須遵守這個標准。
http特性:
HTTP 是無連接無狀態的
HTTP 一般構建於 TCP/IP 協議之上,默認端口號是 80
HTTP 可以分為兩個部分,即請求和響應。
http請求:
HTTP 定義了在與服務器交互的不同方式,最常用的方法有 4 種
分別是 GET,POST,PUT, DELETE。URL 全稱為資源描述符,可以這么認為:一個 URL 地址
對應着一個網絡上的資源,而 HTTP 中的 GET,POST,PUT,DELETE
就對應着對這個資源的查詢,修改,增添,刪除4個操作。
HTTP 請求由 3 個部分構成,分別是:狀態行,請求頭(Request Header),請求正文。
HTTP 響應由 3 個部分構成,分別是:狀態行,響應頭(Response Header),響應正文。
HTTP 響應中包含一個狀態碼,用來表示服務器對客戶端響應的結果。
狀態碼一般由3位構成:
1xx : 表示請求已經接受了,繼續處理。
2xx : 表示請求已經處理掉了。
3xx : 重定向。
4xx : 一般表示客戶端有錯誤,請求無法實現。
5xx : 一般為服務器端的錯誤。
比如常見的狀態碼:
200 OK 客戶端請求成功。
301 Moved Permanently 請求永久重定向。
302 Moved Temporarily 請求臨時重定向。
304 Not Modified 文件未修改,可以直接使用緩存的文件。
400 Bad Request 由於客戶端請求有語法錯誤,不能被服務器所理解。
401 Unauthorized 請求未經授權,無法訪問。
403 Forbidden 服務器收到請求,但是拒絕提供服務。服務器通常會在響應正文中給出不提供服務的原因。
404 Not Found 請求的資源不存在,比如輸入了錯誤的URL。
500 Internal Server Error 服務器發生不可預期的錯誤,導致無法完成客戶端的請求。
503 Service Unavailable 服務器當前不能夠處理客戶端的請求,在一段時間之后,服務器可能會恢復正常。
大概還有一些關於hhtp請求和響應頭信息的介紹。
- 說說Vue原理
Vue是采用數據劫持配合發布者-訂閱者模式,通過Object.defineProperty來()來劫持各個屬性的getter和setter
在數據發生變化的時候,發布消息給依賴收集器,去通知觀察者,做出對應的回調函數去更新視圖。
具體就是:
MVVM作為綁定的入口,整合Observe,Compil和Watcher三者,通過Observe來監聽model的變化
通過Compil來解析編譯模版指令,最終利用Watcher搭起Observe和Compil之前的通信橋梁
從而達到數據變化 => 更新視圖,視圖交互變化(input) => 數據model變更的雙向綁定效果。
- Vue路由守衛有哪些,怎么設置,使用場景等
常用的兩個路由守衛:router.beforeEach 和 router.afterEach
每個守衛方法接收三個參數:
to: Route: 即將要進入的目標 路由對象
from: Route: 當前導航正要離開的路由
next: Function: 一定要調用該方法來 resolve 這個鈎子。
在項目中,一般在beforeEach這個鈎子函數中進行路由跳轉的一些信息判斷。
判斷是否登錄,是否拿到對應的路由權限等等。
- 數組去重
第一種:通過ES6新特性Set()
例如:var arr = [1, 2, 3, 1, 2]; var newArr= [...new Set(arr)]
第二種:封裝函數利用 {} 和【】
function uniqueEasy(arr) {
if(!arr instanceof Array) {
throw Error('當前傳入的不是數組')
}
let list = []
let obj = {}
arr.forEach(item => {
if(!obj[item]) {
list.push(item)
obj[item] = true
}
})
return list
}
當然還有其他的方法,但本人項目中一般使用以上兩種基本滿足
- Set,Map解構
ES6 提供了新的數據結構 Set。
它類似於數組,但是成員的值都是唯一的,沒有重復的值。Set 本身是一個構造函數,用來生成 Set 數據結構。
ES6 提供了 Map 數據結構。它類似於對象,也是鍵值對的集合,但是“鍵”的范圍不限於字符串,各種類型的值(包括對象)都可以當作鍵。
- 對數組排序
第一種方法利用sort方法
第二種利用冒泡排序
- 說一說js是什么語言
js是一種運行在瀏覽器的腳本語言,這種語言主要的功能是可以制作出動態的頁面的效果
我們可以通過js+css+html布局來形成我們現在可以訪問展示的頁面
js語言是弱語言類型, 因此我們在項目開發中當我們隨意更改某個變量的數據類型后
有可能會導致其他引用這個變量的方法中報錯等等。
- 原型
JavaScript中的對象都有一個特殊的 prototype 內置屬性,其實就是對其他對象的引用
幾乎所有的對象在創建時 prototype 屬性都會被賦予一個非空的值,我們可以把這個屬性當作一個備用的倉庫
當試圖引用對象的屬性時會觸發get操作,第一步時檢查對象本身是否有這個屬性,如果有就使用它,沒有就去原型中查找。一層層向上直到Object.prototype頂層
基於原型擴展描述一下原型鏈,什么是原型鏈,原型的繼承,ES5和ES6繼承與不同點。
- ES6新特性
1.ES6引入來嚴格模式
變量必須聲明后在使用
函數的參數不能有同名屬性, 否則報錯
不能使用with語句 (說實話我基本沒用過)
不能對只讀屬性賦值, 否則報錯
不能使用前綴0表示八進制數,否則報錯 (說實話我基本沒用過)
不能刪除不可刪除的數據, 否則報錯
不能刪除變量delete prop, 會報錯, 只能刪除屬性delete global[prop]
eval不會在它的外層作用域引入變量
eval和arguments不能被重新賦值
arguments不會自動反映函數參數的變化
不能使用arguments.caller (說實話我基本沒用過)
不能使用arguments.callee (說實話我基本沒用過)
禁止this指向全局對象
不能使用fn.caller和fn.arguments獲取函數調用的堆棧 (說實話我基本沒用過)
增加了保留字(比如protected、static和interface)
2.關於let和const新增的變量聲明
3.變量的解構賦值
4.字符串的擴展
includes():返回布爾值,表示是否找到了參數字符串。
startsWith():返回布爾值,表示參數字符串是否在原字符串的頭部。
endsWith():返回布爾值,表示參數字符串是否在原字符串的尾部。
5.數值的擴展
Number.isFinite()用來檢查一個數值是否為有限的(finite)。
Number.isNaN()用來檢查一個值是否為NaN。
6.函數的擴展
函數參數指定默認值
7.數組的擴展
擴展運算符
8.對象的擴展
對象的解構
9.新增symbol數據類型
10.Set 和 Map 數據結構
ES6 提供了新的數據結構 Set。它類似於數組,但是成員的值都是唯一的,沒有重復的值。Set 本身是一個構造函數,用來生成 Set 數據結構。
Map它類似於對象,也是鍵值對的集合,但是“鍵”的范圍不限於字符串,各種類型的值(包括對象)都可以當作鍵。
11.Proxy
Proxy 可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問
都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。
Proxy 這個詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”。
Vue3.0使用了proxy
12.Promise
Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。
特點是:
對象的狀態不受外界影響。
一旦狀態改變,就不會再變,任何時候都可以得到這個結果。
13.async 函數
async函數對 Generator 函數的區別:
(1)內置執行器。
Generator 函數的執行必須靠執行器,而async函數自帶執行器。也就是說,async函數的執行,與普通函數一模一樣,只要一行。
(2)更好的語義。
async和await,比起星號和yield,語義更清楚了。async表示函數里有異步操作,await表示緊跟在后面的表達式需要等待結果。
(3)正常情況下,await命令后面是一個 Promise 對象。如果不是,會被轉成一個立即resolve的 Promise 對象。
(4)返回值是 Promise。
async函數的返回值是 Promise 對象,這比 Generator 函數的返回值是 Iterator 對象方便多了。你可以用then方法指定下一步的操作。
14.Class
class跟let、const一樣:不存在變量提升、不能重復聲明...
ES6 的class可以看作只是一個語法糖,它的絕大部分功能
ES5 都可以做到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。
15.Module
ES6 的模塊自動采用嚴格模式,不管你有沒有在模塊頭部加上"use strict";。
import和export命令以及export和export default的區別
- Css3新特性
1.過渡 transition
2.動畫 animation
3.形狀轉換 transform
4.陰影 box-shadow
5.濾鏡 Filter
6.顏色 rgba
7.柵格布局 gird
8.彈性布局 flex
等等還多...
- 說一說你用過的UI框架
Element-UI Vant
- 說一說什么是跨域,怎么解決
因為瀏覽器出於安全考慮,有同源策略。也就是說,如果協議、域名或者端口有一個不同就是跨域,Ajax 請求會失敗。
為來防止CSRF攻擊
1.JSONP
JSONP 的原理很簡單,就是利用 <script> 標簽沒有跨域限制的漏洞。
通過 <script> 標簽指向一個需要訪問的地址並提供一個回調函數來接收數據當需要通訊時。
<script src="http://domain/api?param1=a¶m2=b&callback=jsonp"></script>
<script>
function jsonp(data) {
console.log(data)
}
</script>
JSONP 使用簡單且兼容性不錯,但是只限於 get 請求。
2.CORS
CORS 需要瀏覽器和后端同時支持。IE 8 和 9 需要通過 XDomainRequest 來實現。
3.document.domain
該方式只能用於二級域名相同的情況下,比如 a.test.com 和 b.test.com 適用於該方式。
只需要給頁面添加 document.domain = 'test.com' 表示二級域名都相同就可以實現跨域
4.webpack配置proxyTable設置開發環境跨域
5.nginx代理跨域
6.iframe跨域
7.postMessage
這種方式通常用於獲取嵌入頁面中的第三方頁面數據。一個頁面發送消息,另一個頁面判斷來源並接收消息
- 說一說前端性能優化方案
三個方面來說明前端性能優化
一: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.代碼優化等等
- 說一說SessionStorage和localStorage還有cookie
共同點:都是保存在瀏覽器端、且同源的
不同點:
1.cookie數據始終在同源的http請求中攜帶(即使不需要),即cookie在瀏覽器和服務器間來回傳遞。
cookie數據還有路徑(path)的概念,可以限制cookie只屬於某個路徑下
sessionStorage和localStorage不會自動把數據發送給服務器,僅在本地保存。
2.存儲大小限制也不同,cookie數據不能超過4K,sessionStorage和localStorage可以達到5M
3.sessionStorage:僅在當前瀏覽器窗口關閉之前有效;
localStorage:始終有效,窗口或瀏覽器關閉也一直保存,本地存儲,因此用作持久數據;
cookie:只在設置的cookie過期時間之前有效,即使窗口關閉或瀏覽器關閉
4.作用域不同
sessionStorage:不在不同的瀏覽器窗口中共享,即使是同一個頁面;
localstorage:在所有同源窗口中都是共享的;也就是說只要瀏覽器不關閉,數據仍然存在
cookie: 也是在所有同源窗口中都是共享的.也就是說只要瀏覽器不關閉,數據仍然存在
- 說一說你用過的css布局
gird布局,layout布局,flex布局,雙飛翼,聖杯布局等
- Promise是什么,解決了什么,之前怎么實現的
Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。
解決來之前在請求中回調請求產生的回調地獄,使得現在的代碼更加合理更加優雅,也更加容易定位查找問題。
- 說說瀏覽器緩存
緩存可以減少網絡 IO 消耗,提高訪問速度。瀏覽器緩存是一種操作簡單、效果顯著的前端性能優化手段
很多時候,大家傾向於將瀏覽器緩存簡單地理解為“HTTP 緩存”。
但事實上,瀏覽器緩存機制有四個方面,它們按照獲取資源時請求的優先級依次排列如下:
Memory Cache
Service Worker Cache
HTTP Cache
Push Cache
緩存它又分為強緩存和協商緩存。優先級較高的是強緩存,在命中強緩存失敗的情況下,才會走協商緩存
實現強緩存,過去我們一直用 expires。
當服務器返回響應時,在 Response Headers 中將過期時間寫入 expires 字段,現在一般使用Cache-Control 兩者同時出現使用Cache-Control
協商緩存,Last-Modified 是一個時間戳,如果我們啟用了協商緩存,它會在首次請求時隨着 Response Headers 返回:每次請求去判斷這個時間戳是否發生變化。
從而去決定你是304讀取緩存還是給你返回最新的數據
三面
HR談薪水,問一些公司方面待遇方面,為啥要離職之類的。這個就要看你怎么說來,說得好薪資多點。說不好薪資就要被壓一些,重點就是不要說上家公司的壞話,可以談談你日后的發展方向,准備專精於某個方面,例如數據可視化之類的
結尾
面試題還在持續總結中,如果答案有錯誤請指出方便修正。