【查漏補缺】那些漏掉的面試知識

EvenyYl丶發表於2020-11-28

前言

    查漏補缺,查漏補缺,你不知道哪裡漏了,怎麼補缺呢?因為本文有一萬多字,有點長,所以建議你可以先看看我的面經【查】到自己哪裡【漏】了,再回來【補缺】(騰訊、百度、小米、網易等實習面經

    本文是對自己的前段時間面試的一篇題目及解答總結。其實本來自己是不太想繼續寫關於面試題的文章了,因為社群內很多這類的文章,但是如果每個地方翻一下,又不方便自己回顧,所以還是決定寫下本文供自己鞏固

HTML5

1.新特性

  • 語義標籤

  • 增強型表單

    • 新增表單屬性:placehodler,autofocus,multiple,required,minlength,maxlength,max,min,pattern
  • 視訊和音訊

    • HTML5 提供了播放音訊檔案的標準,即使用 <audio><video> 元素
  • Canvas繪圖

    • 標籤只是圖形容器,必須使用指令碼來繪製圖形
  • SVG繪圖

  • HTML5 Geolocation(地理定位)用於定位使用者的位置

  • 拖放API

    • ondragstart: 元素開始被拖動時觸發 作用在拖拽元素上
    • ondragenter:當拖曳元素進入目標元素的時候觸發的事件,作用在目標元素上
    • ondragover:拖拽元素在目標元素上移動的時候觸發的事件,作用在目標元素上
    • ondragleave:拖拽元素拖離開了目標元素時觸發,作用在目標元素上
    • ondrop:被拖拽的元素在目標元素上同時滑鼠放開觸發的事件,作用在目標元素上
    • ondragend:當拖拽完成後觸發的事件,作用在被拖曳元素上
  • WebWorker

  • WebStorage(這個老生常談了,就不展開了)

  • WebSocket

CSS

1.CSS選擇器

CSS 幾種常見選擇器優先順序是:!important > 內聯 > ID選擇器 > 類選擇器 > 標籤選擇器 > 通用選擇器

  • ID選擇器
  • 類選擇器
  • 標籤選擇器
  • 後代元素選擇器
    • 作用:選中指定元素的指定後代元素。語法:祖先元素 後代元素 {}(空格隔開)
  • 子元素選擇器
    • 作用:選擇指定父元素的指定子元素。語法:父元素 > 子元素
  • 偽類
    • 偽類 表示元素的一種特殊狀態
    • :active 向被啟用的元素新增樣式
    • :focus 向擁有鍵盤輸入焦點的元素新增樣式
    • :hover 當滑鼠懸浮在元素上方時,向元素新增樣式
    • :link 向未被訪問的連結新增樣式
    • :visited 向已被訪問的連結新增樣式。(隱私問題只能設定顏色)
    • :first-child 向元素的第一個子元素新增樣式
    • :lang 向帶有指定 lang 屬性的元素新增樣式
    • ::selection 匹配被使用者選中或處於高亮狀態的部分
  • 偽元素
    • :偽元素 表示元素中一些特殊的位置
    • :first-letter 向文字的第一個字母新增特殊樣式。
    • :first-line 向文字的首行新增特殊樣式。
    • :before 在元素之前新增內容。
    • :after 在元素之後新增內容
  • 其他子元素選擇器
    • :first-child 指定父元素中第一個元素且為指定元素的樣式

2.如何清除浮動

  • 給浮動元素的父元素新增高度
  • 在最後一個子元素新新增最後一個冗餘元素,然後將其設定clear:both,這樣就可以清除浮動
  • 偽元素清除( 手寫clearfix )
.clearfix:after {
    content: '';
    display: block;
    clear: both;
}
  • 給父元素使用overflow:hidden

3.em、rem區別

  • em可以說是相對於父級元素的字型大小,當父級元素字型大小改變時,又得重新計算
  • rem只相對於根目錄,即HTML元素。有了rem這個單位,我們只需要調整根元素htmlfont-size就能達到所有元素的動態適配了

4.重繪與迴流(重排)

重繪不一定導致迴流,迴流一定會導致重繪

  • 迴流:當我們對 DOM 的修改引發了 DOM 幾何尺寸的變化(比如修改元素的寬、高或隱藏元素等)時,瀏覽器需要重新計算元素的幾何屬性(其他元素的幾何屬性和位置也會因此受到影響),然後再將計算的結果繪製出來。這個過程就是迴流(也叫重排)

    • 最“貴”的操作:改變 DOM 元素的幾何屬性
    • “價格適中”的操作:改變 DOM 樹的結構
    • 最容易被忽略的操作:獲取一些特定屬性的值。當你要用到像這樣的屬性:offsetTopoffsetLeftoffsetWidthoffsetHeightscrollTopscrollLeftscrollWidthscrollHeightclientTopclientLeftclientWidthclientHeight
  • 重繪:當我們對 DOM 的修改導致了樣式的變化、卻並未影響其幾何屬性(比如修改了顏色或背景色)時,瀏覽器不需重新計算元素的幾何屬性、直接為該元素繪製新的樣式(跳過了上圖所示的迴流環節)。這個過程叫做重繪

5.position粘性定位

sticky 粘性定位( 建議結合具體實踐操作來進行理解,有的面試官會深挖 )

  • sticky 英文字面意思是粘,貼上,所以可以把它稱之為粘性定位

  • position: sticky; 基於使用者的滾動位置來定位

  • 粘性定位的元素是依賴於使用者的滾動,在 position:relativeposition:fixed 定位之間切換

  • 它的行為就像 position:relative; 而當頁面滾動超出目標區域時,它的表現就像position:fixed;,它會固定在目標位置

  • 元素定位表現為在跨越特定閾值前為相對定位,之後為固定定位

  • 這個特定閾值指的是 toprightbottomleft 之一,換言之,指定 toprightbottomleft 四個閾值其中之一,才可使粘性定位生效。否則其行為與相對定位相同

6.display:none與visibility:hidden

display:none

  • 如果給一個元素設定了display: none,那麼該元素以及它的所有後代元素都會隱藏,它是前端開發人員使用頻率最高的一種隱藏方式。隱藏後的元素無法點選,無法使用螢幕閱讀器等輔助裝置訪問,佔據的空間消失

visibility: hidden

  • 給元素設定visibility: hidden也可以隱藏這個元素,但是隱藏元素仍需佔用與未隱藏時一樣的空間,也就是說雖然元素不可見了,但是仍然會影響頁面佈局

7.style在body前與在body後的區別

  • 寫在body標籤前利於瀏覽器逐步渲染
  • 寫在body標籤後:由於瀏覽器以逐行方式對html文件進行解析,當解析到寫在尾部的樣式表(外聯或寫在style標籤)會導致瀏覽器停止之前的渲染,等待載入且解析樣式表完成之後重新渲染

8.Flex實現的原理

  • 面試時候遇到的一個問題,我想的答案應該是flex底層原理,但至今還是沒查到有關資料,(也有可能是我理解錯意思了,難道面試官只是要我講講他的容器、屬性之類的?)歡迎掘友們評論區指點

9.標準盒子模型於IE盒子模型區別

  • 兩者width不一樣,標準盒子模型的 Width = content,IE盒子模型的Width = border + padding + content

10.z-index失效的場景

主要考察對層疊上下文的概念、以及層疊順序、層疊等級的優先順序問題(具體學習請參考徹底搞懂CSS層疊上下文、層疊等級、層疊順序、z-index

  • 層疊上下文:層疊上下文(stacking context),是HTML中一個三維的概念。在CSS2.1規範中,每個盒模型的位置是三維的,分別是平面畫布上的X軸,Y軸以及表示層疊的Z軸。一般情況下,元素在頁面上沿X軸Y軸平鋪,我們察覺不到它們在Z軸上的層疊關係。而一旦元素髮生堆疊,這時就能發現某個元素可能覆蓋了另一個元素或者被另一個元素覆蓋

  • 層疊等級:在同一個層疊上下文中,它描述定義的是該層疊上下文中的層疊上下文元素在Z軸上的上下順序

  • 如何產生“層疊上下文”

    • HTML中的根元素本身j就具有層疊上下文,稱為“根層疊上下文”
    • 普通元素設定position屬性為非static值並設定z-index屬性為具體數值,產生層疊上下文
    • CSS3中的新屬性也可以產生層疊上下文
  • 層疊順序:按照如下圖排列

11.CSSOM生成規則

構建CSSOM(CSS物件模型 - CSS Object Model)

  • 構建CSSOM的過程與構建DOM的過程非常相似,當瀏覽器接收到一段CSS,瀏覽器首先要做的是識別出Token,然後構建節點並生成CSSOM(規則如下)
  • BytescharacterstokensnodesCSSOM

JS

1.var、let、const區別

1.1 var

  • var宣告的變數不存在塊作用域
  • var宣告的全域性變數會自動變成window物件的屬性
  • var宣告的變數會提升(宣告會提前,但賦值不會,還是會報undefined的錯)
  • var宣告的變數在同一個作用域下可以被重複宣告,而letconst 則不被允許,否則報錯

1.2 let和const

  • let命令,用來宣告變數它的用法類似於var,但是所宣告的變數,只在let命令所在的程式碼塊內有效
  • const宣告一個只讀的常量。一旦宣告,常量的值就不能改變
  • 暫時性死區
    • ES6 明確規定,如果區塊中存在let和const命令,這個區塊對這些命令宣告的變數,從一開始就形成了封閉作用域。凡是在宣告之前就使用這些變數,就會報錯
    var tmp = 123;
    if (true) {
      tmp = 'abc'; // ReferenceError報錯
      let tmp;
    }
    

2.賦值、深拷貝、淺拷貝區別

  • 當我們把一個物件賦值給一個新的變數時,賦的其實是該物件的在棧中的地址,而不是堆中的資料。也就是兩個物件指向的是同一個儲存空間,無論哪個物件發生改變,其實都是改變的儲存空間的內容,因此,兩個物件是聯動的。

  • 淺拷貝:重新在堆中建立記憶體,拷貝前後物件的基本資料型別互不影響,但拷貝前後物件的引用型別因共享同一塊記憶體,會相互影響。

  • 深拷貝:從堆記憶體中開闢一個新的區域存放新物件,對物件中的子物件進行遞迴拷貝,拷貝前後的兩個物件互不影響

3.箭頭函式

  • 語法更加簡潔、清晰 。從上面的箭頭函式基本語法示例中可以看出,箭頭函式的定義要比普通函式定義簡潔、清晰得多,很快捷

  • 箭頭函式沒有 prototype (原型),所以箭頭函式本身沒有this

  • 箭頭函式沒有自己的this,箭頭函式的this指向在定義(注意:是定義時,不是呼叫時)的時候繼承自外層第一個普通函式的this。所以,箭頭函式中 this 的指向在它被定義的時候就已經確定了,之後永遠不會改變

  • 箭頭函式不繫結arguments,取而代之用rest引數...代替arguments物件,來訪問箭頭函式的引數列表。箭頭函式沒有自己的arguments物件。在箭頭函式中訪問arguments實際上獲得的是外層區域性(函式)執行環境中的值

4.apply、call、bind作用及區別

4.1 共同點

  • 三者都是用來改變函式的上下文,也就是改變this指向

4.2 不同點

  • bind 不會立即呼叫,而是返回一個繫結後的新函式。使用場景即:不需要立即指向的,而是像生成一個新的函式長期繫結某個函式給某個物件使用的時候
let newFn = fn.bind(this.Obj)
newFn(arg1,arg2,arg3...)
  • callapply 都是立即呼叫使用
    • apply 是立即呼叫的,返回函式的執行結果,this指向第一個引數,第二個引數是一個陣列,這個陣列裡的內容是fn函式的引數(fn.apply(this.Obj,[arg1,arg2,...]))。使用場景:要傳遞的引數很多,則可以用陣列將引數好呼叫
    • call 也是立即呼叫的,返回函式的執行結果,this指向第一個引數,後面可有多個引數,並且這些都是fn函式的引數(fn.call(this.Obj,arg1,arg2...))。使用場景:要傳遞的引數不多,則可以使用

5.陣列及字元的各種API方法

5.1 陣列

  • 建立陣列

    • Array() let arr = new Array()
    • [] let arr = []
    • Array.of() Array.of(1,2,3) // [1,2,3]
  • 檢測陣列

    • Array.isArray(value)
  • 轉換方法:

    • toLocaleString()
    • toString()
    •   let colors = ['red','yellow', 'blue'];
        console.log(colors.toString()) // red,blue,green
        console.log(colors.toLocaleString()) // red,blue,green
      
  • 棧方法:

    • push() 在陣列末尾新增元素(會修改原陣列),返回修改後的陣列的長度
    • pop() 從陣列的末尾移除最後一項(會修改原陣列),減少陣列的長度,返回刪除的項
  • 佇列方法:

    • shift() 移除陣列中的第一項(會修改原陣列),並返回該項
    • unshift() 在陣列前端新增任意個元素(會修改原陣列),並返回陣列的長度
  • 運算元組方法:

    • reverse() 反轉陣列(會修改原陣列),並返回排序後的陣列

    • sort() 預設情況下,按照升序排列陣列項,呼叫每個陣列項的toString()方法,然後比較得到的字串,確定如何排序(會修改原陣列)。也可以接受一個函式。返排序後的陣列

    • concat() 用於連線兩個或多個陣列arrayObject.concat(arrayX,arrayX,......,arrayX),會先建立當前陣列的一個副本,然後將接受到的引數新增到這個副本的末尾,最後返回數新構建的陣列(不會修改原陣列

    • slice() 基於當前陣列中的一個或多個項建立一個新陣列,接受一或兩個引數,既要返回的起始和結束位置(不會改變原陣列

    • splice() 第一個引數起始位置,第二引數刪除幾個,第三個引數要插入的任意項。splice返回的是刪除的項組成的陣列,沒有則返回空(可進行刪除、插入、替換操作)(會修改原陣列)

    • fill() 該方法方法使用給定值,填充一個陣列(會修改原陣列)

     ['a', 'b', 'c'].fill(7)
     // [7, 7, 7]
     new Array(3).fill(7)
     // [7, 7, 7]
    

    還可以接收第二和第三個引數,用於指定填充的起始位置和結束位置

     ['a', 'b', 'c'].fill(7, 1, 2)
     // ['a', 7, 'c']
    
    • flat() 用於將巢狀的陣列“拉平”,變成以為陣列,返回一個新陣列。接收一個引數,表示想要拉平的層數(不改變原陣列
  • 查位置方法:

    • indexOf()lastIndexOf()
      • indexOf()lastIndexOf()都接收兩個引數:要查詢的項和表示查詢起點位置的索引。indexOf方法從陣列的頭部開始查詢,lastIndexOf方法從陣列的尾部開始查詢。沒找到則返回-1
    • findIndex() 返回第一個符合條件的陣列成員位置,沒找到返回-1,兩個引數:每一項處理函式和(可選的)執行該函式的作用域物件
    [1, 5, 10, 15].findIndex(function(value, index, arr) {//依次當前的值、當前的位置和原陣列
     	return value > 9;
    }) // 2
    
  • 查值方法:

    • find() 查詢出第一個符合條件的陣列成員,接收兩個引數:一個遍歷每一項的函式和(可選的)執行該函式的作用域物件
    [1, 4, -5, 10].find((n) => n < 0) // -5
    
    • includes() 返回一個布林值,接收兩個引數:要查詢的項和表示查詢起點位置的索引
  • 迭代方法:

    • every 對陣列中的每一項執行給定函式,如果該函式對每一項都返回true,則返回true,否則返回false(即全對即返回true,否則都返回false

    • some 與前者相對,該方法是隻傳入的函式對陣列中的某一項返回true,就會返回true(即全錯即返回false,否則有一項符合都返回true

    • filter 返回符合篩選條件的項所組成的一個新陣列(不會改變原陣列

    let number = [1,2,3,4,5];
     let filterResult = number.filter((item, index, array)=>{
         return item > 2
     })
    console.log(filterResult)// [3, 4, 5]
    
    • forEach 它只是對陣列中的每一項執行傳入的函式。沒有返回值(遍歷操作原陣列,會修改原陣列)

    • map 返回一個新陣列,而這個陣列的每一項都是在原始陣列中的對應項上執行傳入函式的結果(不會改變原陣列

    let number = [1,2,3,4,5];
     let mapResult = number.map((item, index, array)=>{
         return item * 2
     })
    console.log(mapResult)// [2, 4, 6, 8, 10]
    

6.遍歷物件的方法

  • for in 主要用於遍歷物件的可列舉屬性,包括自有屬性、繼承自原型的屬性
var obj = {"name":"tom","sex":"male"}

Object.defineProperty(obj, "age", {value:"18", enumerable:false})
//增加不可列舉的屬性age

Object.prototype.protoPer1 = function(){console.log("name is tom");}
//通過原型鏈增加屬性,為一個函式

Object.prototype.protoPer2 = 2 //通過原型鏈增加屬性,為一個整型值2

for(var a in obj){
	console.log(a)
    console.log(obj[a])
}
//	示例中的屬性age為不可可列舉,所以沒有輸出
  • Object.keys 此方法返回一個陣列,元素均為物件自有可列舉的屬性
//	(示例為上面程式碼)
console.log(Object.keys(obj))
//	["name","sex"]
  • Object.getOwnProperty 此方法用於返回物件的自有屬性,包括可列舉和不可列舉的屬性
//	(示例為上面程式碼)
console.log(Object.getOwnPropertyNames(obj))
//	["name","sex","age"]

7.Es6常見新特性

  • ES6類 Class
  • for…of 和 for…in
  • 物件的解構
  • rest操作符 / Spread操作符
  • 模板字串
  • const let
  • promise
  • async函式
  • Module

8.Set、Map、WeakSet 和 WeakMap 的區別

詳細區別請參考阮一峰老師的 ECMAScript 6 入門 Set 和 Map 資料結構

  • 集合(Set)ES6 提供了新的資料結構 Set。它類似於陣列,但是成員的值都是唯一的,沒有重複的值

  • 對映(Map)是用於存取鍵值對的資料結構,一個鍵只能對應一個值且鍵不能重複

  • WeakSet結構和Set類似,都是不重複值的集合

    • WeakSet的成員只能是物件,而不能是其他的值
    • WeakSet中的物件都是弱引用,即垃圾回收機制不考慮WeakSet對該物件的引用,也就是說,如果其他物件都不再引用該物件。那麼垃圾回收機制會自動會輸該物件所佔用的額記憶體,不考慮該物件還存在與WeakSet之中
  • WeakMap結構與Map結構類似,也是用於生成鍵值對的集合

    • WeakMap只接受物件作為鍵名(null除外),不接受其他型別的值作為鍵名
    • WeakMap的鍵名所指向的物件,不計入垃圾回收機制

9.對原型、原型鏈的理解

      像c語言有類實現繼承、java可以通過抽象類實現繼承,而js為了能將一類事物抽象出來,使相同一類事物能夠擁有一樣的屬性跟方法,便將原型鏈作為實現繼承的主要方式。原型鏈從資料結構來看,其實就是一個連結串列,例項有一個指向原型的指標,原型又包含一個指向建構函式的指標,層層遞進

10.瀏覽器事件流的階段以及事件監聽的三個引數

DOM事件傳播包括三個階段:

  • 1、捕獲階段
  • 2、目標物件呼叫事件處理程式
  • 3、冒泡階段
    第三個引數為true就走捕獲階段,為false就走冒泡階段。捕獲是不可被取消的,但冒泡可以。繫結事件預設是冒泡階段

11.閉包使用問題

      由於閉包會使得函式中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能導致記憶體洩露。解決方法是,在退出函式之前,將不使用的區域性變數全部刪除

12.如何清除閉包

      閉包的含義是函式在呼叫時能夠訪問函式在定義時可以訪問的作用域,例如在定義函式a的時候,a能夠訪問變數b。每一個函式都有自己對應的閉包,當函式沒有被垃圾回收機制回收時函式對應的閉包也會常駐記憶體。如果需要清除閉包就要回收不需要的函式,根據JavaScript回收機制,當一個記憶體空間沒有變數指向的時候就會被回收。那麼閉包清除的方式就是將不需要的函式名賦值為null

框架

1.vue的data為什麼是一個方法

  • 因為元件是用來複用的,且 JS 裡物件是引用關係,如果元件中 data 是一個物件,那麼這樣作用域沒有隔離,子元件中的 data 屬性值會相互影響,如果元件中 data 選項是一個函式,那麼每個例項可以維護一份被返回物件的獨立的拷貝,元件例項之間的 data 屬性值不會互相影響;而 new Vue 的例項,是不會被複用的,因此不存在引用物件的問題

  • 一個元件被複用多次的話,也就會建立多個例項。本質上,這些例項用的都是同一個建構函式。如果data是物件的話,物件屬於引用型別,會影響到所有的例項。所以為了保證元件不同的例項之間data不衝突,data必須是一個函式

2.vue元件間通訊問題

一般的父子元件、祖孫元件傳值、Vuex應該都能答上來,但你能答得更清晰更全面嗎?或許可以讓面試官眼前一亮哦(請檢視參考文章 Vue元件通訊方式居然有這麼多?你瞭解幾種

3.watch監聽實現


簡單闡述原理(具體瞭解請檢視官方原始碼):vm 呼叫 $watch 後,首先呼叫 observe 函式 建立 Observer 例項觀察資料,Observer 又建立 Dep , Dep 用來維護訂閱者。然後建立 Watcher 例項提供 update函式。一旦資料變動,就層層執行回撥函式

4.vue-router的hash跟history模式

4.1 hash模式

hash模式, 原本用來結合錨點控制頁面視窗的位置,具有以下特點:

  • 在hash模式下,所有的頁面跳轉都是客戶端進行操作,因此對於頁面攔截更加靈活;但每次url的改變不屬於一次http請求,所以不利於SEO優化

  • hash 模式是一種把前端路由的路徑用井號 # 拼接在真實 URL 後面的模式。當井號 # 後面的路徑發生變化時,瀏覽器並不會重新發起請求,而是會觸發 hashchange 事件。

  • 可以改變URL,但不會觸發頁面重新載入(hash的改變會記錄在window.hisotry中)因此並不算是一次http請求,所以這種模式不利於SEO優化

  • 只能修改#後面的部分,因此只能跳轉與當前URL同文件的URL

  • 只能通過字串改變URL

  • 通過window.onhashchange監聽hash的改變,藉此實現無重新整理跳轉的功能

4.2 history模式

history模式, 根據 Mozilla Develop Network 的介紹,呼叫 history.pushState() 相比於直接修改 hash,存在以下優勢

  • history API 是 H5 提供的新特性,允許開發者直接更改前端路由,即更新瀏覽器 URL 地址而不重新發起請求

  • 新的URL可以是與當前URL同源的任意 URL,也可以與當前URL一樣,但是這樣會把重複的一次操作記錄到棧中

  • 通過引數stateObject可以新增任意型別的資料到記錄中

  • 可額外設定title屬性供後續使用

  • 通過pushStatereplaceState實現無重新整理跳轉的功能

  • 相容性不如 hash,且需要服務端支援,否則一重新整理頁面就404了

  • history模式下,藉助history.pushState實現頁面的無重新整理跳轉;這種方式URL的改變屬於http請求,因此會重新請求伺服器,這也使得我們必須在服務端配置好地址,否則服務端會返回404,為確保不出問題,最好在專案中配置404頁面

5.vue3 Proxy跟vue2 defineProperty區別

5.1 defineProperty缺點

  • 無法檢測物件屬性的新增或移除,為此我們需要使用 Vue.setVue.delete 來保證響應系統的執行符合預期
  • 無法監控到陣列下標及陣列長度的變化,當直接通過陣列的下標給陣列設定值或者改變陣列長度時,不能實時響應
  • 效能問題,當data中資料比較多且層級很深的時候,因為要遍歷data中所有的資料並給其設定成響應式的,會導致效能下降

5.2 對比區別

  • Object.defineProperty只能劫持物件的屬性,對新增屬性需要手動進行 Observe,而 Proxy 是直接代理物件
  • 為什麼 Proxy 可以解決以上的痛點呢? 本質的原因在於 Proxy 是一個內建了攔截器的物件,所有的外部訪問都得先經過這一層攔截。不管是先前就定義好的,還是新新增屬性,訪問時都會被攔截(proxy具體學習請看阮一峰老師的ES6教程 Proxy

6.computed和watch區別

6.1 概念

  • computed: 是計算屬性,依賴其它屬性值,並且 computed 的值有快取,只有它依賴的屬性值發生改變,下一次獲取 computed 的值時才會重新計算 computed的值
  • watch: 更多的是「觀察」的作用,類似於某些資料的監聽回撥 ,每當監聽的資料變化時都會執行回撥進行後續操作

6.2 區別

  • 相同: computedwatch都起到監聽/依賴一個資料,並進行處理的作用
  • 不同:它們其實都是vue對監聽器的實現,只不過computed主要用於對同步資料的處理,watch則主要用於觀測某個值的變化去完成一段開銷較大的複雜業務邏輯。能用computed的時候優先用computed,避免了多個資料影響其中某個資料時多次呼叫watch的尷尬情況

7.在哪個生命週期內呼叫非同步請求

可以在鉤子函式 createdbeforeMountmounted 中進行呼叫,因為在這三個鉤子函式中,data 已經建立,可以將服務端端返回的資料進行賦值。但是本人推薦在 created 鉤子函式中呼叫非同步請求,因為在 created 鉤子函式中呼叫非同步請求有以下優點

  • 能更快獲取到服務端資料,減少頁面 loading 時間
  • ssr 不支援 beforeMountmounted 鉤子函式,所以放在 created 中有助於一致性

8.虛擬DOM

8.1 虛擬DOM有什麼好處?

  • 假設一次操作中有10次更新DOM的動作,虛擬DOM不會立即操作DOM,而是將這10次更新的diff內容儲存到本地一個JS物件中,最終將這個JS物件一次性attchDOM樹上,再進行後續操作,避免大量無謂的計算量。所以,用JS物件模擬DOM節點的好處是,頁面的更新可以先全部反映在虛擬DOM上,操作記憶體中的JS物件的速度顯然要更快,等更新完成後,再將最終的JS物件對映成真實的DOM,交由瀏覽器去繪製

8.2 通過DIFF演算法對比操作JS物件實現差量更新

  • 沒有舊的節點,則建立新的節點,並插入父節點。
  • 如果沒有新的節點,則摧毀舊的節點。
  • 如果節點發生了變化,則用replaceChild改變節點資訊
  • 如果節點沒有變化,則對比該節點的子節點進行判斷,使用遞迴呼叫

8.3 虛擬DOM實際渲染規則

Vue和React通用流程:vue template/react jsx -> render函式 -> 生成VNode -> 當有變化時,新老VNode diff -> diff演算法對比,並真正去更新真實DOM

9.Vue3 新特性

  • Composition API(看圖,解決開發者在完成或閱讀程式碼時上下反覆跳轉,同一個功能的程式碼不夠聚合的問題)
    • 使用亮點:整個函式就是一個功能;函式包含建立新資料夾所依賴的資料和邏輯;函式完全獨立,功能可以複用
  • 告別$set
    • 即上面提到的Proxy重寫了資料雙向繫結的方法解決了痛點問題
  • Fragments
    • 簡單來說就是,在vue3中元件官方支援宣告多個根節點了。也就是說,下面這樣的寫法是可行的。同時需要我們顯示的宣告在何處分發,同時意味著render函式也可以返回陣列了attribute
  • Vue3.0將對tsxclass component等有更好的支援
  • destroyed 生命週期重新命名為 unmounted
  • beforeDestroy 生命週期重新命名為 beforeUnmount

10.vue底層重寫陣列的七個方法

10.1 概述

Vue監聽Array三步曲(只是大體原理,具體請自己檢視官方原始碼進行理解或者檢視一些關於VUE原始碼的權威書籍)

  • 第一步:先獲取原生 Array 的原型方法,因為攔截後還是需要原生的方法幫我們實現陣列的變化
  • 第二步:對 Array 的原型方法使用 Object.defineProperty 做一些攔截操作
  • 第三步:把需要被攔截的 Array 型別的資料原型指向改造後原型

10.2 重寫的陣列方法

push()pop()shift()unshift()splice()sort()reverse()

11.vue、react區別

11.1 相同點

  • 都是元件化開發思想
  • 都支援伺服器端渲染
  • 都採用Virtual DOM,元件化開發,通過props引數進行父子元件資料的傳遞,都實現webComponent規範
  • 資料驅動檢視
  • 都有支援native的方案,React的React native,Vue的weex
  • 都有管理狀態,React有redux,Vue有自己的Vuex(自適應vue,量身定做)

11.2 不同點

  • React嚴格上只針對MVC的view層,Vue則是MVVM模式
  • virtual DOM不一樣,vue會跟蹤每一個元件的依賴關係,不需要重新渲染整個元件樹;而對於React而言,每當應用的狀態被改變時,全部元件都會重新渲染,所以react中會需要shouldComponentUpdate這個生命週期函式方法來進行控制
  • 元件寫法不一樣,React推薦的做法是 JSX + inline style,也就是把HTMLCSS全都寫進JavaScript了,即all in js;Vue推薦的做法是webpack+vue-loade的單檔案元件格式,即htmlcssjs寫在同一個檔案
  • 資料繫結:vue實現了資料的雙向繫結,react資料流動是單向的
  • state物件在react應用中不可變的,需要使用setState方法更新狀態;在vue中,state物件不是必須的,資料由data屬性在vue物件中管理;

12.keep-alive

  • keep-alive是Vue.js的一個內建元件。<keep-alive> 包裹動態元件時,會快取不活動的元件例項,而不是銷燬它們。它自身不會渲染一個 DOM 元素,也不會出現在父元件鏈中。 當元件在 <keep-alive> 內被切換,它的 activateddeactivated 這兩個生命週期鉤子函式將會被對應執行。它提供了includeexclude兩個屬性,允許元件有條件地進行快取

13.vuex

13.1 vuex核心:

  • state:儲存store的各種狀態
  • mutation: 改變store的狀態只能通過mutation方法
  • action: 非同步操作方法
  • module: 模組化
  • getter: 相當於計算屬性,過濾出來一些值

13.2 vuex使用

  • 每一個 Vuex 應用的核心就是 store(倉庫)。“store”基本上就是一個容器,它包含著你的應用中大部分的狀態 (state)。Vuex 和單純的全域性物件有以下兩點不同:

  • Vuex 的狀態儲存是響應式的。當 Vue 元件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的元件也會相應地得到高效更新。

  • 你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地瞭解我們的應用

計算機網路

1.DNS解析

DNS (Domain Name System 的縮寫)的作用非常簡單,通俗來講就是根據域名查出IP地址

1.1 DNS解析順序

  • 本地hosts檔案
  • 本地DNS快取
  • DNS伺服器快取
  • DNS伺服器遞迴查詢

1.2 DNS的記錄型別

當我們在阿里雲買了一個域名後,可以配置我們主機域名解析規則,也就是 記錄
常見的 DNS 記錄型別如下

  • A:地址記錄(Address),返回域名指向的IP地址
  • NS:域名伺服器記錄(Name Server),返回儲存下一級域名資訊的伺服器地址。該記錄只能設定為域名,不能設定為IP地址
  • MX:郵件記錄(Mail eXchange),返回接收電子郵件的伺服器地址
  • CNAME:規範名稱記錄(Canonical Name),返回另一個域名,即當前查詢的域名是另一個域名的跳轉
  • PTR:逆向查詢記錄(Pointer Record),只用於從IP地址查詢域名

1.3 DNS遞迴查詢

DNS伺服器是怎麼遞迴查詢的,(以這個地址為例tlab.cloud.tencent.com. 600 IN A 193.112.230.97

  • 詢問根域名,獲取頂級域名 .comNS(Name Server)A(Address)NS為頂級域名的名字,ANS對應的ip地址
  • 詢問頂級域名,獲取二級域名 .tencnet.comNSA
  • 詢問二級域名,獲取三級域名 .cloud.tencent.com 的NS 和 A
  • 詢問三級域名,獲取四級域名 .tlab.cloud.tencent.com 的NS 和 A
  • 最後,將tlab.cloud.tencent.com的ip地址返回給使用者,並且快取
  • 使用者獲取到真正的ip地址,並且快取

2.Http1 和 Http2 區別

2.1 HTTP/1.1 缺點

  • 隊頭阻塞(Head-of-line blocking)

    • HTTP/1.1協議雖然可以在同一個TCP連線上傳送多個請求,但是這多個請求是有順序的,必須處理完第一個請求才會響應下一個請求。如果第一個請求處理的特別慢,後面的所有請求就需要排隊。
  • TCP 連線數限制

    • 對於同一個域名,瀏覽器最多隻能同時建立 6 ~ 8 個TCP連線。如果一個頁面有十個請求同時傳送,那麼只能等第一次的 6 ~ 8 個請求都返回了才能繼續接下來的 2 ~ 4 個請求。這怎麼能行?域名分片技術應運而生。就是把資源分配到不同的域名下(可以是二級子域名),這樣就解決了限制,愉快~但是濫用域名分片技術也不行,因為每個TCP連線也是很費時的(這個大家都懂的)。
  • Header 內容繁多,有時有可能會超過響應內容,並且每次有許多欄位都是重複傳輸。

  • HTTP/1.1是文字協議傳輸,不夠安全

2.2 HTTP2相比於HTTP/1.1的新特性包括:

  • 多路複用 (MultiPlexing),單一長連線,二進位制格式傳輸,請求優先順序設定

  • 頭部header壓縮

  • 服務端推送Server Push

3.Http 和 Https區別

HTTPS和HTTP的主要區別 (多了一層SSL or TSL)

  • 1、https協議需要到ca申請證照,一般免費證照較少,因而需要一定費用

  • 2、http是超文字傳輸協議,資訊是明文傳輸,https則是具有安全性的ssl加密傳輸協議

  • 3、http和https使用的是完全不同的連線方式,用的埠也不一樣,前者是80,後者是443

  • 4、http的連線很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網路協議,比http協議安全

4.協商快取跟強快取區別

5.get、post區別

  • GET 請求引數會被完整保留在瀏覽器歷史記錄裡,而POST中的引數不會被保留

  • GET 引數通過URL傳遞,POST放在Request body中。GETPOST更不安全,因為引數直接暴露在URL上,所以不能用來傳遞敏感資訊

  • GET 用於獲取資訊,POST 用於修改伺服器上的資料(一般情況下遵循這個規則)

  • 《圖解HTTP》對這兩者的說明的區別

    • GET :用來請求訪問已被URI識別的資源
    • POST :用來傳輸實體的主體(POSTGET功能很相似,但是POST的主要目的不是獲取相應的主體內容)

6.Cookie與Session的區別

  • cookie資料存放在客戶的瀏覽器(客戶端)上,session資料放在伺服器上,但是服務端的session的實現對客戶端的cookie有依賴關係的

  • cookie不是很安全,別人可以分析存放在本地的COOKIE並進行COOKIE欺騙,考慮到安全應當使用session

  • session會在一定時間內儲存在伺服器上。當訪問增多,會比較佔用你伺服器的效能。考慮到減輕伺服器效能方面,應當使用COOKIE

  • 單個cookie在客戶端的限制是4K,就是說一個站點在客戶端存放的COOKIE不能超過4K

7.用axios給每個請求頭前統一加一個欄位

    使用axios request 攔截器,axios.interceptors.request.use

總結

      下一次再寫面試相關文章可能要到春招了,也是我這名21屆學生的DDL了。因為面試發現一些問題深挖就會答得很含糊,究其根本就是因為自己看的書不夠多,很多概念沒有一個認知,只知其表,不知其裡(本文中很多解答也是一樣的,如果你只看這些簡要概念,那麼你面試的時候,一旦面試官深挖,那麼你就答不上來了,建議大家還是抽空去看看書,看看官方文件)。所以之後一段時間應該都是邊實習邊抽空看書,完善自己的整個知識體系,我之後可能也會寫一些關於書籍中知識的文章。

寫在文末

    如果你覺得我寫得還不錯的話,可以給我點個贊哦^^,如果哪裡寫錯了、寫得不好的地方,也請大家評論指出,以供我糾正

其它文章

相關文章