2019年前端面試題總結

HTML

1. 重繪與迴流

一個頁面從加載到完成,首先生成DOM樹,而後根據DOM節點的幾何屬性生成render樹(渲染樹),當渲染樹構建完成,頁面開始根據DOM樹佈局,渲染樹也會根據設置的樣式渲染節點javascript

迴流: 當咱們刪除或修改元素高度時,頁面會從新佈局,DOM樹發生變化,引發渲染樹從新渲染,這個過程叫作迴流(迴流必定形成重繪css

重繪: 當修改元素的顏色,渲染樹會根據新規則從新渲染,這個過程叫作重繪(重繪不必定形成迴流html

如何減小回流前端

  1. 對DOM進行屢次添加刪除操做時,使用documentfragment對象(在該對象中對DOM進行操做,完成後append到文檔中,便可只進行一次迴流)
    function addDivs(element) {
      var div;
      // Creates a new empty DocumentFragment.
      var fragment = document.createDocumentFragment();
      for (var i = 0; i < 20; i ++) {
        div = document.createElement('a');
        div.innerHTML = 'Heya!';
        fragment.appendChild(div);
      }
      element.appendChild(fragment);
    }
    複製代碼
  2. 使用定位脫離文檔流改變位置
  3. 避免逐項更改樣式,將樣式列表定義爲class並一次性更改class屬性
  4. 避免循環讀取offsetLeft等屬性,在循環以前把它們緩存起來。

2. 獲取點擊元素的下標

------ html-------
<ul>
    <li>Coffee</li>
    <li>Milk</li>
    <li>Soda</li>
</ul>
複製代碼
  1. 原生js
let lis = document.getElementsByTagName('li')
for (let i=0; i<lis.length; i++) {
  lis[i].index = i
}
document.getElementsByTagName('ul')[0].addEventListener('click', handle, false)
function handle (event) {
  if (event.target.tagName === 'LI') {
    console.log(event.target.index)
  }
}
複製代碼
  1. jquery的index()方法
$('li').click(function () {
  console.log($(this).index())
})
複製代碼

CSS

1. css佈局,實現頂部高固定,左側導航寬固定,右側自適應

點我ԅ(¯﹃¯ԅ)vue

2. 三大定位,相對定位放在固定定位產生什麼影響?

fixed、relative、absolutejava

相對定位和固定定位,都會使塊級元素產生BFC,下面經過步驟檢測一下node

  1. 設置父元素爲固定定位,不設置高度,內部box設置高度和寬度,根據BFC內部box垂直排列的特徵,效果以下jquery

    <div class="sj">
        <div>1</div>
    </div>
    複製代碼
    .sj{
        position: fixed;
        top: 0;
        left: 0;
        width: 200px;
        background-color: #ccc;
      }
      .sj>div{
        height: 20px;
        width: 100px;
        background-color: #2db7f5;
      }
    複製代碼
    1. 若將內部box設爲絕對定位,即內部box會產生BFC,根據BFC與外部互不影響的特徵,內部box將沒法撐起父元素高度,以下

    .sj>div{
        height: 20px;
        width: 100px;
        position: absolute;
        background-color: #2db7f5;
    }
    複製代碼

3. 僞類和僞元素

僞類:向某些選擇器設置特殊效果,用於選擇器選擇不到的元素webpack

僞元素:向某些選擇器添加特殊效果web

  • 僞類本質爲了彌補選擇器的不足,以此獲取更多信息
  • 僞元素建立一個新的虛擬容器,該容器內不包含dom節點,但能夠添加內容,而且可對僞元素追加樣式
  • 僞類「:」,僞元素「::」
  • 能夠同時使用多個僞類,但同時只能使用一個僞元素

4. 純css畫三角形

點我ԅ(¯﹃¯ԅ)

5. CSS BFC是什麼?

BFC是一個獨立的塊級渲染容器,擁有本身的渲染規則,不受外部影響,不影響外部

特徵

  1. 內部box垂直往下排列
  2. 內部塊元素受maigin特徵的影響,上下外邊距會塌陷
  3. BFC區域不會遮蓋浮動元素區域
  4. 計算BFC高度時,浮動元素高度也計算在內
  5. BFC是獨立渲染容器,外部元素不影響內部,反之亦然

產生條件

  1. 固定定位和絕對定位
  2. float除了none外
  3. overflow除了visible外(hidden、auto、scroll)
  4. display爲如下其一(inline-block、table-cell、table-caption)

做用

  1. 清除浮動
  2. 消除margin重疊
  3. 佈局(左浮動,右BFC自適應)

6. 清除浮動的方式

1. 父元素設置僞類:clear:both + zoom:1

設置zomm爲了兼容IE

<div class="parent1 clearFloat">
    <div class="left"></div>
</div>
<div class="parent2"></div>

.parent1{
    border: 1px solid red;
}
.parent2{
    height: 100px;
    border: 1px solid blue;
}
.left{
    width: 200px;
    height: 200px;
    background-color: #5cadff;
    float: left;
}
.clearfloat::after{
    display: block;
    clear: both;
    content: '';
    visibility: hidden;
    height: 0;
}
.clearfloat {
    zoom: 1
}
複製代碼

2. 結尾處添加空白標籤:claer:both

<div class="parent1">
    <div class="left"></div>
    <div class="clearfloat"></div>
</div>
<div class="parent2"></div>

.clearfloat{
    clear: both;
}
複製代碼

3. 父元素產生BFC

BFC內浮動元素高度計算在內

7. 水平垂直居中的實現方式,儘量多

方法1、定位 + transform

.parent{
    height: 500px;
    width: 500px;
    border: 1px solid red;
    position: relative;
 }
 .child{
    height: 80px;
    width: 80px;
    background-color: #515A6E;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
 }
複製代碼

方法2、margin + transform

.parent{
    height: 500px;
    width: 500px;
    border: 1px solid red;
 }
 .child{
    height: 80px;
    width: 80px;
    background-color: #515A6E;
    margin: 50% 0 0 50%;
    transform: translate(-50%, -50%);
 }
複製代碼

方法3、定位 + 負margin

.parent{
    height: 500px;
    width: 500px;
    border: 1px solid red;
    position: relative;
 }
 .child{
    height: 80px;
    width: 80px;
    background-color: #515A6E;
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -40px 0 0 -40px;
 }
複製代碼

方法4、flex

.parent{
    height: 500px;
    width: 500px;
    border: 1px solid red;
    display: flex;
    align-items: center;
    justify-content: center;
 }
 .child{
    height: 80px;
    width: 80px;
    background-color: #515A6E;
 }
複製代碼

方法5、table-cell

.parent{
    height: 500px;
    width: 500px;
    border: 1px solid red;
    display: table-cell;
    text-align: center;
    vertical-align: middle;
 }
 .child{
    display: inline-block;
    height: 80px;
    width: 80px;
    background-color: #515A6E;
 }
複製代碼

8. 盒子模型

標準盒子模型

width = content

IE盒子模型

width = border + padding + content

9. 塊級元素和行內元素的區別?img可設置寬高嗎?

塊級元素

  • 獨佔一行,在默認狀況下,其寬度自動填滿其父元素的寬度
  • 塊級元素能夠設置width、height屬性
  • 塊級元素即便設置了寬度也是獨佔一行,塊級元素能夠設置margin、padding屬性

行內元素

  • 行內元素不會獨佔一行,相鄰的行內元素會排列在同一行裏,直到行排不下,就自動換行,其寬度隨內容而變化
  • 行內元素的width、height屬性則無效
  • 水平方向的padding、margin會產生邊距效果,豎直方向的padding、margin不會產生邊距效果

行內置換元素

瀏覽器依據元素的標籤和屬性來決定元素的具體顯示內容

img、input、textarea、select、object屬於行內置換元素, 具備塊級元素的特徵(除寬度外)

10. absolute定位 不設置top、right、bottom、left有什麼效果?

元素脫離文檔流,但由於沒有設置屬性致使沒法具體定位,緊跟在上個元素以後,但下個元素排列時會忽略此元素

11. css權重

<div id="a">
  <span class="b">222</span> // 紅色
</div>

div span{
  color: blue;
}
#a {
  color: red;
}
複製代碼

!important(10000) > 內聯樣式(1000) > id(100) > class|僞類|屬性選擇(10) > 標籤|僞元素(1) > 通配符(0) > 繼承(無)

JavaScript

1. js輸出數組中出現最多的元素和次數

點我ԅ(¯﹃¯ԅ)

2. 100階臺階一次走1步或2步有多少種走法

假設只走一個臺階,有1種走法;兩個臺階,2中走法,三個臺階,3種走法;四個臺階,5種走法...

1->1; 2->2; 3->3; 4->5...能夠看出此問題是斐波那契數列,即下個值是前兩個值的和

公式爲:f(n) = f(n-1) + f(n-2)

方法1、遍歷相加

function test (num) {
    let num1 = 1, num2 = 2, res = 0
      for (let i=2; i<num; i++) {
        res = num1 + num2
        num1 = num2
        num2 = res
      }
    return res
}
複製代碼

方法2、遞歸 (不推薦)

function test (num) {
    if (num === 1)
        return 1
    else if (num === 2)
        return 2
    else 
        return test(num-1) + test(num-2)
}
複製代碼

3. 如何實現抽獎轉盤

4. 閉包及使用場景

  • 閉包

    1. 外部函數可以訪問內部函數的變量
    2. 閉包所在的函數變量不能被垃圾回收機制回收
    3. 常駐內存,佔用內存使用量
  • 使用場景

    1. 給對象設置私有變量而且利用特權方法去訪問私有屬性
    2. 採用函數引用方式的setTimeout調用
    3. 封裝相關功能集

    👉傳送門

5. 什麼是原型、原型鏈?

  • 原型對象也是普通的對象,是對象一個自帶隱式的__proto__屬性,原型也有可能有本身的原型,若是一個原型對象的原型不爲null的話,咱們就稱之爲原型鏈。
  • 原型鏈是由一些用來繼承和共享屬性的對象組成的(有限的)對象鏈。

6. 類的建立與繼承

  • 建立:new 一個Function,在prototype中添加屬性和方法
  • 繼承:
    1. 原型鏈繼承,基於原型鏈,是父類和子類的實例,沒法實現多繼承
    function Cat(){}
    Cat.prototype = new Animal();
    Cat.prototype.name = 'cat';
    //&emsp;Test Code
    var cat = new Cat();
    複製代碼
    1. 構造函數繼承:複製父類的實例給子類,只繼承父類實例的屬性與方法,不繼承原型上的,可實現多繼承
    function Cat(name){
        Animal.call(this)
        this.name = name || 'Tom';
    }
    var cat = new Cat()
    複製代碼
    1. 組合繼承(原型鏈繼承+構造函數繼承)

7. new作了什麼事

  • 建立一個空對象
  • 將該對象的原型指向建立該對象的構造函數的prototype上

8.建立對象的方式

  1. 工廠模式
  2. 構造函數模式
  3. 原型模式
  4. 混合構造函數與原型模式

9. 深拷貝

  • 數組的深拷貝
let newArr = JSON.Parse(JSON.Stringify(oldArr))
複製代碼
擴展運算符
<!-- 僅對包含基本數據類型的數組有效 -->
let newArr = [...oldArr]
複製代碼
  • 對象的深拷貝
function deepClone (obj) {
    let newObj = obj instanceof Array ? [] : {}
    for(var i in obj){
        newObj[i] = typeof obj[i] == 'object' ? deepClone(obj[i]) : obj[i]
    }
    return newObj
}
複製代碼

10. 數組操做

傳送門👉 JavaScript 數組

11. 寫一個js函數,實現對一個數字每3位加一個逗號

function test (num) {
    let arr1 = [], arr2 = [],arr = [] // arr1保存小數前, arr2保存小數後
    arr = num.toString().split('.')
    arr2 = arr[1] ? [...arr[1]] : [] // 判斷是否存在小數,並將每項轉爲數組元素
    arr1 = [...arr[0]]
    let newArr1 = arr1.map((item, index) => arr1.length === (index+1) && (index+1)%3 === 0 ? item : (index+1)%3 === 0 ? item+',' : item)
    let newArr2 = arr2.map((item, index) => arr2.length === (index+1) && (index+1)%3 === 0 ? item : (index+1)%3 === 0 ? item+',' : item)  // 數組爲空則map()不檢測
    newArr2.unshift('.')
    console.log(newArr1.concat(newArr2).join(''))
  }
  test(123456789.123)
複製代碼

12. 手寫快速排序

快速排序採用分治法的思想,將一個複雜問題分爲兩個或多個子問題,直到子問題簡單到能夠直接求解,那麼子問題的解的組合即是原問題的解

function quickSort (arr) {
    if (arr.length <= 1) return arr;
    //取中間位置的數據做爲基準值,並從原數組中刪除該基準值
    let jzIndex = Math.floor(arr.length/2) // 獲取基準值下標
    let jzNum = arr.splice(jzIndex, 1) // 刪除並獲取基準值

    let leftArr = [], rightArr = [] // 分別保存小於和大於基準值的數據
    arr.forEach(item => {
      if (item < jzNum[0]) {
        leftArr.push(item)
      }
      if (item >= jzNum[0]) {
        rightArr.push(item)
      }
    })
    //concat()鏈接兩個數組
    return quickSort(leftArr).concat(jzNum, quickSort(rightArr))
  }
  console.log(quickSort([10,5,15,2,4]))
複製代碼

13. 函數的防抖與節流

防抖: 任務頻繁觸發狀況下,只有兩次任務間隔超過指定時間,纔會執行。若還未超過卻又一次觸發,則時間從新開始計算

// 防抖函數
  function debounce (fn, time) {
    // 新建一個變量保存定時器
    let timeout = null;
    return function () {
      // 每次用戶點擊、輸入時,清空上一個定時器
      clearTimeout(timeout)
      timeout = setTimeout(() => {
        fn.call(this, arguments)
      }, time)
    }
  }
  // 處理函數
  function handler () {
    console.log('防抖成功!')
  }
  // 觸發
  debounce(handler, 1000)
複製代碼

節流: 頻繁觸發任務,任務按照必定時間間隔進行執行

// 節流函數
  function throttle (fn, time) {
    // 利用閉包保存是否可執行的變量
    let canRun = true
    return function () {
      // 若是爲false,則終止函數執行
      if (!canRun) return;
      // 執行前將變量設爲false
      canRun = false
      setTimeout(() => {
        fn.call(this, arguments)
        canRun = true
      }, time)
    }
  }
  // 處理函數
  function handler () {
    console.log('節流成功!')
  }
  // 觸發
  throttle(throttle, 1000)
複製代碼

14. 隨機生成指定範圍內的隨機數

在指定範圍內生成隨機數

ES6

1. Promise相關問題

1. 什麼是Promise?

  • promise是異步編程的解決方案,比起傳統的異步解決方案「回調函數」、「事件」更合理強大,已被ES6歸入規範
  • 具備三種狀態:pending 過渡態、fulfilled 完成態、rejected 失敗態,狀態一旦肯定不可修改

2. Promise優缺點?

優勢:

  • 解決回調地域
  • 可讀性高,便於維護

缺點:

  • 沒法中止,一旦建立Promise當即執行
  • 必須指定回調,不然內部拋出異常
  • 當處於pending狀態時,沒法肯定此時進行到哪一階段(剛開始仍是即將完成)

3. Promise的方法有哪些?做用都是什麼?

  • Promise.prototype.then()

    Promise 實例添加狀態改變時的回調函數,then方法的第一個參數是resolved狀態的回調函數,第二個參數(可選)是rejected狀態的回調函數

    then方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例)。所以能夠採用鏈式寫法,即then方法後面再調用另外一個then方法。

  • Promise.prototype.catch()

    .then(null, rejection)或.then(undefined, rejection)的別名,用於指定發生錯誤時的回調函數。

  • Promise.prototype.finally()

    不管Promise最後狀態如何,都會執行finally內的函數,ES2018引入

  • Promise.all()

    多個Promise同時執行,若所有成功,則以數組形式返回執行結果;如有一個是rejected,則只返回rejected的結果

  • Promise.race()

    多個Promise同時執行,返回最早結束Promise執行任務的結果,不管成功或失敗

  • Promise.resolve()

    返回一個新的 Promise 實例,該實例的狀態爲resolve

    1. 若參數爲Promise實例,則返回該實例
    2. 參數是一個thenable對象,(thenable爲具備then方法的對象),將此對象轉換爲Promise並當即執行then方法
    3. 參數不是具備then方法的對象,或根本就不是對象,則Promise.resolve方法返回一個新的 Promise 對象,狀態爲resolved
    4. 若不帶任何參數,直接返回一個resolved狀態的 Promise 對象
  • Promise.reject()

    返回一個新的 Promise 實例,該實例的狀態爲rejected

4. promise如何使用?

  • Promise是構造函數,須要new一個Promise的實例
  • Promise構造函數的參數爲一個函數,函數內的參數爲resolved和rejected
  • 實例後用then方法分別指定resolved狀態和rejected狀態的回調函數
  • then方法接受兩個參數,rejected非必須;then返回Promise對象,則可鏈式調用

5. 手寫一個promise

// 定義Promise構造函數
  function Promise (exector) {
    let self = this;
    this.value = undefined;
    this.reason = undefined;
    // 定義Promise的狀態
    this.status = 'pending'
    // 存儲then中成功的回調函數
    this.onResolvedCallbacks = [];
    // 存儲then中失敗的回調函數
    this.onRejectedCallbacks = [];

    function resolve (value) {
      if (self.status === 'pending') {
        self.value = value
        self.status = 'resolved'
        self.onResolvedCallbacks.forEach(fn => fn())
      }
    }

    function reject (reason) {
      if (self.status === 'pending') {
        self.reason = reason
        self.status = 'rejected'
        self.onRejectedCallbacks.forEach(fn => fn())
      }
    }
    // 異常處理
    try{
      exector(resolve, reject)
    }catch (e) {
      reject(e)
    }
  }

  // 在Promise原型上定義then方法,參數爲成功和失敗的回調
  Promise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    if (this.status === 'resolved') {
      onFulfilled(self.value)
    }
    if (this.status === 'rejected') {
      onRejected(self.reason);
    }
    if (this.status === 'pending') {
      this.onResolvedCallbacks.push(() => {
        onFulfilled(self.value)
      })

      this.onRejectedCallbacks.push(() => {
        onRejected(self.reason)
      })
    }
  }

  let promise = new Promise((resolve, reject)=> {
    setTimeout(() => {
      resolve('success')
    }, 1000)
  })

  promise.then(data => {
    console.log(data)
  }, err => {
    console.log(err)
  })
複製代碼

webpack

webpack是模塊打包工具,對js模塊和擴展語言進行打包供瀏覽器識別運行

  • webpack只能處理js代碼,其餘格式須要經過loader進行轉換
  • 可對瀏覽器不能識別的規範和靜態文件進行分析、壓縮、合併、打包成可供瀏覽器支持的代碼

1. webpack和Grunt以及Gulp相比有什麼區別

2. webpack 的 loader 和 plugin 區別,舉幾個經常使用的 loader 和 plugin 並說出做用

  • loader用於對模塊代碼進行轉換,可將不一樣格式語言轉換爲JavaScript,或將圖像轉換爲Data Url,因爲webpack只可以識別JavaScript,因此不一樣類型的模塊須要對應的loader進行轉換
  • plugin是webpack的擴展插件,可完成loader沒法完成的複雜功能,可控制webpack每一個打包環節的流程,極大豐富了webpack的擴展性

3. webpack打包過程

  • 讀取文件,分析模塊的依賴
  • 對模塊進行解析執行(深度遍歷)
  • 針對不一樣的模塊使用不一樣的 loader
  • 編譯模塊,生成抽象語法樹(AST)
  • 遍歷 AST,輸出 JS

4. webpack打包優化

  • 使用compression-webpack-plugin壓縮代碼
  • 使用cdn引入第三方庫
  • 按需引入第三方庫裏不一樣組件

Vue

1. 兄弟組件如何通訊,無嵌套,回調觸發

方法1、經過父組件通訊

此方法須要保證兄弟組件A、B都在同一個父組件下;

父組件經過接受子組件A傳遞過來的事件消息,並調用子組件B

子組件A
this.$emit('transmit', 'msg')
複製代碼
父組件
<ChildA @transmit="transmit"></ChildA>
<ChildB :msg="msg"></ChildB>

transmit (data) => {
    this.msg = data 
}
複製代碼
子組件B、須要使用watch來監聽父組件props穿過來的數據變化
watch (new, old) {
    數據操做... 
}
複製代碼

方法2、eventBus

經過建立Bus.js註冊一個全局實例,通信組件經過調用實例的方法達到通信目的

  1. 建立Bus.js
// eventBus 共享vue實例,用於兄弟組件數據傳遞
import Vue from 'vue'
const Bus = new Vue({})
export {Bus}
複製代碼
  1. 組件A導入Bus.js 並emit消息
import {Bus} from './Bus.js'

Bus.$emit('transmit', 'msg')
複製代碼
  1. 組件B導入Bus.js並在mounted中檢測數據變化
import {Bus} from './Bus.js'

mounted () {
    Bus.$on('transmit', (data) => {
        操做...
    })
}

因爲$on事件沒法主動銷燬,因此須要根據業務手動進行銷燬

在組件銷燬前方法中銷燬
beforeDestory () {
    Bus.$off('transmit')
}

或者在使用前進行銷燬
mounted () {
    Bus.$off('transmit')
    Bus.$on('transmit', (data) => {
        操做...
    })
}
複製代碼

2. vueRouter的工做原理

Vue Router 是路由管理器,能夠改變url而不向服務器發送請求,頁面無需刷新

有hash和history兩種路由模式

hash模式

  • #後的hash值改變,會觸發onhashchange事件
  • hash的變化會被瀏覽器記錄(歷史訪問棧)下來,能夠前進、後退、刷新而不向服務器發送請求
  • 經過匹配#後面的hash,與vueRouter配置文件裏的path對應作路由跳轉

history模式

  • 基於瀏覽器history的pushState()、replaceState()、popState()來實現,能夠讀取、修改瀏覽器歷史記錄棧
  • 能夠前進、後退不發往服務器發送請求,但刷新會向服務器發送請求
  • 若匹配不到資源,則返回404,所以須要後臺支持,重定向到根目錄主頁

動態路由匹配中會複用同一組件,這就致使再次訪問組件不被從新渲染,聲明週期鉤子不會執行,這就須要咱們用watch去監聽路由的變化

watch: {
    $route(to, from) {
        ······
    }
}
複製代碼

vue Router 詳解

3. Vuex的理解

Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式

Vuex包含五個屬性:state、getter、mutation、action、module

  • state:存儲數據,存儲狀態;註冊了Store實例後,可經過this.$store.XX來訪問;對應組件內的data,數據爲響應式,組件經過store來讀取vuex的數據,若數據改變,則組件的數據也會改變
  • getter:store的計算屬性,它的返回值會被依賴緩存起來,當依賴值發生變化時纔會被從新計算
  • mutation:更改Vuex的store中狀態的惟一方法是提交mutation
  • action:包含任意異步操做,經過提交 mutation 間接更變狀態
  • module:將 store 分割成模塊,每一個模塊都具備state、mutation、action、getter、甚至是嵌套子模塊

當組件進行數據修改的時候,經過調用dispatch來觸發actions裏面的方法,actions裏每一個方法都有commit方法,經過執行commit方法來觸發mutation裏的方法進行數據修改,因爲mutation裏每一個函數都有一個state參數,進而可對state進行修改,當數據修改完畢後,會傳導給頁面。頁面的數據也會發生改變。

4. vue Dom渲染的過程和原理

  • new Vue 初始化Vue實例
  • 經過三種渲染模式 Render、el、template 生成Render函數
  • 經過Watcher監測數據變化
  • 當數據變化時,經過Render函數生成VNode
  • 經過patchVnode對比先後變化,經過diff進行更新、添加、刪除等操做生成真實Dom節點

5. watch用法

watch用來監聽並響應數據的變化

  • 能夠直接監聽基本數據類型數據
  • 如果監聽對象,則須要開啓deep(深度監聽)
  • 如果監聽數組,則不須要開啓deep監聽
  • immediate 初始化綁定值時即執行監聽
  • watch首次初始化綁定不執行,但監聽的值發生變化時則執行監聽
data () {
    return {
        age: 20,
        obj: {
            age: 24
        },
        arr: [1,2,3]
    }
}
複製代碼
1. 監聽基本類型
watch: {
    age (newd, oldd) {
        ...
    }
}

複製代碼
2. 監聽對象
watch: {
    obj: {
        handler (newd, oldd) {
            ...
        },
        deep: true, // 開啓深度監聽
        immediate: true // 首次即執行
    }
}
複製代碼
3. 監聽對象某個屬性

*** 採用字符串
watch: {
    'obj.age': {
        handler (newd, oldd) {
            ...
        }
    }
}

*** 利用computed計算屬性
computed: {
    age () {
        return this.obj.age
    }
}
watch: {
    age (newd, oldd) {
        ...
    }
    // 也可寫爲
    age: {
        handler (newd, oldd) {
            ...
        }
    }
}
複製代碼

6. vue nextTick

異步更新隊列

Vue 異步執行 DOM 更新。只要觀察到數據變化,Vue將開啓一個隊列,並緩衝在同一事件循環中發生的全部數據改變。若是同一個 watcher被屢次觸發,只會被推入到隊列中一次。這種在緩衝時去除重複數據對於避免沒必要要的計算和 DOM 操做是很是重要的。而後,在下一個的事件循環「tick」中,Vue刷新隊列並執行實際 (已去重的) 工做。Vue 在內部嘗試對異步隊列使用原生的Promise.then和MessageChannel,若是執行環境不支持,會採用 setTimeout(fn, 0) 代替。

例如,當你設置 vm.someData='newvalue',該組件不會當即從新渲染。當刷新隊列時,組件會在事件循環隊列清空時的下一個「tick」更新

nextTick

因爲DOM是異步執行更新的,有時咱們修改完數據等待DOM更新後進行操做,則此刻可以使用Vue.nextTick(callback)

Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
    return {
      message: '沒有更新'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = '更新完成'
      console.log(this.$el.textContent) // => '沒有更新'
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => '更新完成'
      })
    }
  }
})
複製代碼

由於 $nextTick() 返回一個 Promise 對象,因此你可使用新的ES2016async/await語法完成相同的事情:

methods: {
  updateMessage: async function () {
    this.message = 'updated'
    console.log(this.$el.textContent) // => '未更新'
    await this.$nextTick()
    console.log(this.$el.textContent) // => '已更新'
  }
}
複製代碼

7. vue 生命週期有哪些?

  • beforeCreate ----建立前
  • created ---- 成功建立
  • beforeMount ---- 掛載前
  • mounted ---- 成功掛載
  • beforeUpdate ---- 更新前
  • updated ---- 成功更新
  • beforeDestroy ---- 銷燬前
  • destroyed ---- 成功銷燬

👉傳送門,Vue聲明週期詳解

8. vue 響應式數據是如何實現的?

  1. 遍歷實例中的data的全部屬性,並經過Object.defineProperty將其轉換爲setter、getter
  2. 每一個實例都有一個Watcher、並經過Dep去關聯data中的setter、getter的依賴
  3. 當data改變時,setter會觸發Dep依賴,並觸發Watcher.update
  • 因爲Object.observe的廢除,致使沒法檢測對象的變化
  • 沒法檢測根級對象的屬性變化,可經過Vue.set(this.obj, key, value)來向對象動態添加響應式屬性

網絡

1. 瀏覽器輸入地址後發生什麼

  1. 解析URL
  2. DNS解析、監測緩存
  3. 客戶端與服務端創建TCP鏈接(三次握手)
  4. 請求與傳輸數據
  5. 進行數據渲染
  6. 解析HTML、生成DOM樹、解析CSS代碼、將數據渲染到網頁上

2. 輪詢、長輪詢、長鏈接、websocket區別

  • 輪詢:定時向服務器發送ajax請求,無需等待響應
  • 長輪詢:客戶端向服務器發送請求,服務器保持鏈接,當有更新消息當即返回客戶端,鏈接關閉。
  • 長鏈接:客戶端向服務器發送請求,服務器保持鏈接,當有更新消息當即返回客戶端,鏈接保持。
  • websocket:h5提供的基於TCP的雙向通信協議,服務器主動推送消息到客戶端,只需一次握手鍊接,便可創建持久鏈接

3. 三次握手、四次分手

  • 三次握手
客戶端      ->(創建鏈接)->          服務器
    客戶端   <-(確認接受,創建鏈接)<-   服務器
    客戶端      ->(確認接受)->          服務器
複製代碼
  • 四次分手
客戶端      ->(關閉鏈接)->      服務器
    客戶端      <-(確認關閉)<-      服務器
    客戶端      <-(關閉鏈接)<-      服務器
    客戶端      ->(確認關閉)->      服務器
複製代碼

4. 請求狀態碼

2XX 請求成功

  • 200 請求成功
  • 204 請求成功,但未有任何資源返回
  • 206 服務器成功處理部分get請求)

3XX 重定向

  • 301 url已更新
  • 302 url重定向
  • 303 是否訪問新的url
  • 304 訪問緩存資源,服務器無數據返回

4XX 客戶端錯誤

  • 401 須要驗證
  • 403 不容許訪問

5XX 服務器錯誤

5. 安全問題

XSS(跨站腳本攻擊)是在網頁中注入非法的js腳本,獲取cookie達到控制瀏覽器的目的

  • DOM xss : 使用DOM能夠容許程序和腳本動態的訪問和更新文檔的內容、結構和樣式
  • 反射性 xss:發出請求時,XSS代碼出如今URL中,最後輸入提交到服務器,服務器解析後在響應內容中出現這段XSS代碼,最後瀏覽器解析執行。
  • 存儲型 xss:當攻擊者提交一段XSS代碼後,被服務器端接收並存儲,當全部瀏覽者訪問某個頁面時都會被XSS,其中最典型的例子就是留言板。

危害:

  • 利用虛擬輸入表單獲取用戶信息
  • 獲取cookie,可代替用戶進行危險操做

防範方法:

  • httpOnly: 在 cookie 中設置 HttpOnly 屬性,使js腳本沒法讀取到 cookie 信息
  • 先後端校驗輸入表單格式,過濾不合理字符

CSRF 跨站點請求僞造,冒充用戶發起請求,完成一些違背用戶意願的事情(如修改用戶信息等)

危害:

  • 利用已認證過的用戶對商品信息、我的信息進行違法操做等

防範方法:

  • 驗證碼: 強制用戶與應用進行交互
  • 減小get請求
  • token驗證CSRF防護機制是公認最合適的方案

token使用原理

  • 後端隨機生成一個token,並將此token攜帶在cookie中,而後將此token傳遞給前端頁面
  • 前端獲取此token後,每次請求都攜帶token
  • 後端驗證token是否一致,若一致則請求合法

6. ajax請求過程

  1. 建立XMLHttpRequest對象,
  2. 建立http請求,並指明請求的url,方式和參數
  3. 設置http請求狀態變化的函數
  4. 發送http請求
  5. 經過回調獲取返回的數據
  6. 渲染

7. 跨域的方式

同源策略: 具備相同的協議(http/https)、域名、端口即爲同源,不存在跨域,反之亦然

  • 跨域資源共享(CORS)

    需後端設置

  • 服務器轉發代理

    請求同源地址的代理接口,服務器訪問跨域接口並返回數據

  • jsonp

    利用script標籤不受同源策略限制的特徵,在src內寫入請求地址,末尾回調處理數據

    <script type="text/javascript" src="http://localhost/Service.ashx?callback=jsonpCallback" />
    複製代碼

8. cookie、sessionStorage、localStorage

cookie

  • 存儲大小最大爲4k
  • 老是攜帶於http請求中
  • 需設置max-age,超過期間則被銷燬

sessionStorage

  • 存儲大小最大爲5M
  • 存儲於本地中
  • 當前會話有效,頁面或瀏覽器關閉則銷燬
  • 從A跳轉到B,B可與A共享sessionStorage;若單獨打開B,則獲取爲null

localStorage

  • 存儲大小最大爲5M
  • 存儲於本地中
  • 若未設置過時時間,則永久保存
  • 頁面之間共享

優化

1. 圖片優化

圖片大體分爲png、jpg、gif三種

  • gif體積小,很好的壓縮效果,支持動畫,支持透明效果;但色彩效果最低
  • png壓縮效果好,支持透明效果,色彩不如jpg,最爲通用

優化方案:

  1. 雪碧圖
    • 即css sprites, 就是把不少小圖片製做成一個大圖,而後做爲背景圖片使用,定位便可
    • 優勢: 體積小,引入一張圖片便可,減小http請求
  2. 圖片壓縮
    • 使用canvas的drawImage()進行壓縮
    • 上傳至七牛雲或阿里雲進行壓縮
  3. base64
    • 利用編碼存儲圖片,減小http請求
  4. 響應式圖片
    • 利用srcset 和 sizes 屬性作響應式圖片
  5. 延遲加載
    • 當圖片不少時,所有加載耗時過多也極可能形成卡頓
    • 僅加載可視區域內的圖片,非可視區域使用通用圖片佔位,當頁面滾動進入可視區域後,再加載此區域內的圖片

當加載圖片過大時,會出現局部逐步加載狀況,用戶體驗差;可經過喲圖片的onload方法來判斷圖片是否加載完成,未加載完前先display:none;進行隱藏,當onload後在進行加載。

其餘

1. 輪流向圓形桌子放硬幣,若是保證能贏,誰先放?

假設桌子小到只能放下一枚硬幣,那麼先放者贏;若不肯定桌子大小,則首先在圓心處放硬幣,而後在對手放完後的關於圓心的對稱點處再放硬幣,確保先放者贏

2. 隨機抽樣一致性算法

詳解

相關文章
相關標籤/搜索