2020 前端面試 | 第一波面試題總結

https://juejin.im/post/5e3d898cf265da5732551a56css


前言

先介紹一下本身的狀況吧html

內蒙古呼和浩特某大學畢業,專科,計算機多媒體專業畢業 16年出來工做,工做經驗四年,以前主要作平面相關,本身喜歡瞎折騰,從17年開始研究前端,而後公司內部轉崗到開發部門工做,算下來前端經驗也快三年之久。前端

年末因爲種種緣由想換一份工做,但因爲太忙,沒認真搞簡歷,也沒怎麼複習基礎,致使不少原本會的都沒敢往簡歷上寫。因而寫了一個簡版的簡歷掛在Boss直聘上,準備年過完再認真籌備這件事情。 令我意外的是,近一個月收到多家公司的面試邀請。vue

所以總結一波2020年最新面試題,但願對你們有所幫助!後面的答案爲自行整理,若有疏漏,歡迎指正!node

面試總結

  • 重視基礎和原理webpack

  • 重視基礎和原理nginx

  • 重視基礎和原理web

如下面試均爲電話面試

一面

  • 原型
構造函數是一種特殊的方法,主要用來在建立對象時初始化對象。每一個構造函數都有prototype(原型)屬性,
這個prototype(原型)屬性是一個指針,指向一個對象,這個對象的用途是包含特定類型的全部實例共享的
屬性和方法,即這個原型對象是用來給實例對象共享屬性和方法的。每一個實例對象的__proto__都指向這個
構造函數/類的prototype屬性。

面向對象的三大特性:繼承/多態/封裝

關於new操做符:

1. new執行的函數, 函數內部默認生成了一個對象

2. 函數內部的this默認指向了這個new生成的對象

3. new執行函數生成的這個對象, 是函數的默認返回值

ES5例子:
function Person(obj) {
	this.name = obj.name
	this.age= obj.age
}
// 原型方法
Person.prototype.say = function() {
  console.log('你好,', this.name )
}
// p爲實例化對象,new Person()這個操做稱爲構造函數的實例化
let p = new Person({name: '番茄', age: '27'})
console.log(p.name, p.age)
p.say()

ES6例子:
class Person{
	constructor(obj) {
  	this.name = obj.name
		this.age= obj.age
  }
  say() {
  	console.log(this.name)
  }
}

let p = new Person({name: 'ES6-番茄', age: '27'})
console.log(p.name, p.age)
p.say()
複製代碼

關於原型的繼承咱們藉助寄生組合繼承

function Person(obj) {
    this.name = obj.name
    this.age = obj.age
}
Person.prototype.add = function(value){
    console.log(value)
}
var p1 = new Person({name:"番茄", age: 18})

function Person1(obj) {
    Person.call(this, obj)
    this.sex = obj.sex
}
// 這一步是繼承的關鍵
Person1.prototype = Object.create(Person.prototype)
Person1.prototype.play = function(value){
    console.log(value)
}
var p2 = new Person1({name:"雞蛋", age: 118, sex: "男"})
複製代碼
  • 閉包
首先說明什麼是閉包,閉包簡單來講就是函數嵌套函數,內部函數引用來外部函數的變量,從而致使垃圾回收
機制沒有把當前變量回收掉,這樣的操做帶來了內存泄漏的影響,當內存泄漏到必定程度會影響你的項目運行
變得卡頓等等問題。所以在項目中咱們要儘可能避免內存泄漏。
複製代碼
  • 原型鏈
原型鏈實際上在上面原型的問題中就有涉及到,在原型的繼承中,咱們繼承來多個原型,這裏再提一下實現完美
繼承的方案,經過藉助寄生組合繼承,PersonB.prototype = Object.create(PersonA.prototype)
這是當咱們實例化PersonB獲得實例化對象,訪問實例化對象的屬性時會觸發get方法,它會先在自身屬性上查
找,若是沒有這個屬性,就會去__proto__中查找,一層層向上直到查找到頂層對象Object,這個查找的過程
就是原型鏈來。
複製代碼
  • vuex
vuex是一個專爲vue.js應用程序開發的狀態管理器,它採用集中式存儲管理應用的全部組件的狀態,而且以相
應的規則保證狀態以一種能夠預測的方式發生變化。

state: vuex使用單一狀態樹,用一個對象就包含來所有的應用層級狀態

mutation: 更改vuex中state的狀態的惟一方法就是提交mutation

action: action提交的是mutation,而不是直接變動狀態,action能夠包含任意異步操做

getter: 至關於vue中的computed計算屬性
複製代碼
  • vue-router
vue-router是vuex.js官方的路由管理器,它和vue.js的核心深度集成,讓構建但頁面應用變得易如反掌

<router-link> 組件支持用戶在具備路由功能的應用中 (點擊) 導航。 經過 to 屬性指定目標地址

<router-view> 組件是一個 functional 組件,渲染路徑匹配到的視圖組件。

<keep-alive> 組件是一個用來緩存組件

router.beforeEach

router.afterEach

to: Route: 即將要進入的目標 路由對象

from: Route: 當前導航正要離開的路由

next: Function: 必定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。

介紹了路由守衛及用法,在項目中路由守衛起到的做用等等
複製代碼
  • 深拷貝淺拷貝
淺拷貝:淺拷貝經過ES6新特性Object.assign()或者經過擴展運算法...來達到淺拷貝的目的,淺拷貝修改
副本,不會影響原數據,但缺點是淺拷貝只能拷貝第一層的數據,且都是值類型數據,若是有引用型數據,修改
副本會影響原數據。

深拷貝:經過利用JSON.parse(JSON.stringify())來實現深拷貝的目的,但利用JSON拷貝也是有缺點的,
當要拷貝的數據中含有undefined/function/symbol類型是沒法進行拷貝的,固然咱們想項目開發中須要
深拷貝的數據通常不會含有以上三種類型,若有須要能夠本身在封裝一個函數來實現。
複製代碼
  • Vue通訊
1.props和$emit
2.中央事件總線 EventBus(基本不用)
3.vuex(官方推薦狀態管理器)
4.$parent$children
固然還有一些其餘辦法,但基本不經常使用,或者用起來太複雜來。 介紹來通訊的方式,還能夠擴展說一下使用
場景,如何使用,注意事項之類的。
複製代碼
  • 你在工做終於到那些問題,解決方法是什麼
常常遇到的問題就是Cannot read property ‘prototype’ of undefined
解決辦法經過瀏覽器報錯提示代碼定位問題,解決問題

Vue項目中遇到視圖不更新,方法不執行,埋點不觸發等問題
通常解決方案查看瀏覽器報錯,查看代碼運行到那個階段未之行結束,閱讀源碼以及相關文檔等
而後舉出來最近開發的項目中遇到的算是兩個比較大的問題。
複製代碼
  • webpack配置入口出口
module.exports={
    //入口文件的配置項
    entry:{},
    //出口文件的配置項
    output:{},
    //模塊:例如解讀CSS,圖片如何轉換,壓縮
    module:{},
    //插件,用於生產模版和各項功能
    plugins:[],
    //配置webpack開發服務功能
    devServer:{}
}
簡單描述了一下這幾個屬性是幹什麼的。
描述一下npm run dev / npm run build執行的是哪些文件
經過配置proxyTable來達到開發環境跨域的問題,而後又能夠擴展和他聊聊跨域的產生,如何跨域
最後能夠在聊聊webpack的優化,例如babel-loader的優化,gzip壓縮等等
複製代碼
  • 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 服務器當前不可以處理客戶端的請求,在一段時間以後,服務器可能會恢復正常。

大概還有一些關於http請求和響應頭信息的介紹。
複製代碼
  • 說說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是什麼語言
JavaScript是一種直譯式腳本語言,是一種動態類型、弱類型、基於原型的語言,內置支持類型。它的解釋器被稱爲JavaScript引擎,爲瀏覽器的一部分,普遍用於客戶端的腳本語言,最先是在HTML(標準通用標記語言下的一個應用)網頁上使用,用來給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命令以及exportexport default的區別
複製代碼
  • Css3新特性
1.過渡 transition
2.動畫 animation
3.形狀轉換 transform
4.陰影 box-shadow
5.濾鏡 Filter
6.顏色 rgba
7.柵格佈局 gird
8.彈性佈局 flex
等等還多...
複製代碼
  • 說一說你用過的UI框架
Element-UI Vant Antd
複製代碼
  • 說一說什麼是跨域,怎麼解決
由於瀏覽器出於安全考慮,有同源策略。也就是說,若是協議、域名或者端口有一個不一樣就是跨域,Ajax 請求會失敗。
爲來防止CSRF攻擊
1.JSONP
    JSONP 的原理很簡單,就是利用 <script> 標籤沒有跨域限制的漏洞。
    經過 <script> 標籤指向一個須要訪問的地址並提供一個回調函數來接收數據當須要通信時。
    <script src="http://domain/api?param1=a&param2=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談薪水,問一些公司方面待遇方面,爲啥要離職之類的。這個就要看你怎麼說來,說得好薪資多點。說很差薪資就要被壓一些,重點就是不要說上家公司的壞話,能夠談談你往後的發展方向,準備專精於某個方面,例如數據可視化之類的面試

結尾

面試題還在持續總結中,以上是部分總結的面試題,若是答案有錯誤請指出方便修正。算法

相關文章
相關標籤/搜索