1. 程式人生 > 實用技巧 >面試題2

面試題2

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

HTML

1. 必考:你是如何理解 HTML 語義化的?

html語義化就是在合適的位置使用正確的標籤。比如段落使用p標籤、標題使用h1-h6標籤、文章使用article標籤

html語義化相對於div + css的優點

  1. 網頁結構更清晰
  2. 有利於團隊的開發和維護,便於閱讀理解
  3. 有利於搜尋引擎的檢索抓取
  4. 有利於視覺障礙使用者使用裝置的讀取,如螢幕閱讀器

2. meta viewport 是做什麼用的,怎麼寫?

專為移動裝置下顯示所設計的.只有檢測到在移動裝置上使用包含meta的文件時, meta標籤才會起作用.

手機瀏覽器是把頁面放在一個虛擬的視窗(viewport)中,使用者可以通過平移和縮放來看網頁的不同部分

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  • width:控制 viewport 的寬度,可以指定的具體值或者特殊的值,如 device-width 為裝置的寬度(單位為縮放為 100% 時的 CSS 的畫素)。
  • height:和 width 相對應,指定高度
  • initial-scale:初始縮放比例,即頁面首次載入時的縮放比例
  • maximum-scale:允許使用者縮放到的最大比例
  • minimum-scale:允許使用者縮放到的最小比例
  • user-scalable:使用者是否可以手動縮放

3. 你用過哪些 HTML 5 標籤?

佈局標籤: header footer main article section aside time 
功能標籤: canvas video aduio

4. H5 是什麼?

狹義上的H5是一種程式語言,是HTML5的簡略寫法
廣義上的H5則不同,瀏覽的網頁、使用的微信乃至於手機中的軟體,大部分都有H5的功勞
因此H5在國內網際網路圈涵蓋的範圍極大,凡是使用了H5技術的網頁微信頁面等頁面都可以被稱為H5。H5技術也不僅僅侷限於單純的HTML5了,涵蓋了HTML5、CSS3、JavaScript等一系列前端技術

CSS

1. 必考:兩種盒模型分別說一下

  • 盒子模型組成:分為內容(content)、填充(padding)、邊框(border)和邊界(margin)

  • IE盒模型:屬性width,height包含content、border和padding

  • W3C標準盒模型:屬性width,height只包含內容content,不包含border和padding

  • box-sizing(CSS新增的屬性)用於選擇盒模型

    • content-box: 標準盒模型
    • border-box: IE盒模型

如果在ie6,7,8中DOCTYPE缺失會將盒子模型解釋為IE盒子模型。若在頁面中聲明瞭DOCTYPE型別,所有的瀏覽器都會把盒模型解釋為W3C盒模型

2. 必考:如何垂直居中?

水平居中

  1. 設定一個寬度,然後新增 margin:0 auto 屬性

    /*子盒子有寬度*/
    .child {
    	margin: 0 auto;
    }
    
  2. 利用 text-align:center 實現

    .parent {
        text-align: center;
    }
    .child {
        display: inline-block;
    }
    
  3. 絕對定位 position: absolute + margin-left

    /*子盒子有寬度*/
    .parent {
        position: relative;
    }
    .child {
        position: absolute;
        top:0;
        left: 50%;
        margin-left: -100px; /*子盒子寬度的一半*/
    
  4. 絕對定位 position: absolute + transform

    .parent {
        position: relative;
    }
    .child {
        position: absolute;
        top:0;
        left: 50%;
        transform: translate(-50%);
    }
    
  5. 使用flex佈局

    .parent {
    	display: flex;
        justify-content: center;
    }
    

垂直居中

  1. 單行文字垂直居中

    .parent {
        height: 100px;
        border: 1px solid #ccc; /*設定border是為了方便檢視效果*/
    }
    .child {
        line-height: 100px;
    }
    
  2. 絕對定位 position: absolute + transform

    .parent {
      width: 100%;
      height: 100%;
      position: relative;
    }
    .child {
      width: 500px;
      border: 1px solid #ccc; /*設定border是為了方便檢視效果*/
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
    }
    
  3. 絕對定位 position: absolute + 四邊值相等

    .parent {
        position: relative;
        width: 100%;
        height: 100%;
    }
    .child {
      width: 500px;
      height: 30%;
      border: 1px solid #ccc;
        
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      margin: auto;
    }
    
  4. display:table

.parent {
  width: 100%;
  height: 100%;
  display: table;
}
.child {
  display: table-cell;
  vertical-align: middle;
}

水平垂直居中

  1. 絕對定位 position: absolute + transform

    .container {
        position: relative;
    }
    .box {
        position:absolute;
        top:50%;
        left:50%;
        transform:translate(-50%, -50%);
        /*已知高度寬度,margin-top margin-left設定為本身高度寬度的一般*/
    }
    
  2. 絕對定位 position: absolute + 四邊值相等

      .container {
        width: 500px;
        height: 500px;
        border: 1px solid #000;
        position: relative;
      }
      .box {
        position: absolute;
        width: 200px;
        height: 200px;
        background-color: rgb(247, 207, 207);
        margin: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
      }
    
  3. 使用flex佈局

    .container {
        display:flex;
        justify-content: center;
        align-items:center;
    }
    
  4. 使用grid佈局

      .container {
        width: 500px;
        height: 500px;
        border: 1px solid #000;
          
        display:grid;
      }
      .box {
        position: absolute;
        width: 200px;
        height: 200px;
        background-color: rgb(247, 207, 207);
        
        justify-self:center;
        align-self:center;
      }
    
  5. table-cell

    組合使用display:table-cell和vertical-align、text-align,使父元素內的所有行內元素水平垂直居中

    /*利用 table 的單元格居中效果展示*/
    .container {
        display: table-cell;
        text-align: center;
        vertical-align: middle;
    }
    
  6. vertical-align+inline-block

    .container {
        width: 500px;
        height: 500px;
        border: 1px solid #000;
        text-align: center;
      }
      .container::after {
        content: "";
        display: inline-block;
        vertical-align: middle;
        height: 100%;
      }
      .box {
        width: 200px;
        height: 200px;
        background-color: rgb(247, 207, 207);
        display: inline-block;
        vertical-align: middle;
      }
    

3. 必考:flex 怎麼用,常用屬性有哪些?

Flex是FlexibleBox的縮寫,意為"彈性佈局",用來為盒狀模型提供最大的靈活性

任何一個容器都可以指定為Flex佈局。行內元素也可以使用Flex佈局。注意,設為Flex佈局以後,子元素的float、clear和vertical-align屬性將失效

採用Flex佈局的元素,稱為Flex容器(flexcontainer),簡稱"容器"。它的所有子元素自動成為容器成員,稱為Flex專案(flexitem),簡稱"專案"

容器預設存在兩根軸:水平的主軸(mainaxis)和垂直的交叉軸(crossaxis),專案預設沿主軸排列

設定在容器上的屬性

  • flex-direction——決定主軸的方向(即專案的排列方向)
  • flex-wrap——定義一條軸線排不下時,如何換行
  • flex-flow——是flex-directionflex-wrap的簡寫,預設值為row nowrap
  • justify-content——定義專案在主軸上的對齊方式
  • align-items——定義專案在交叉軸上如何對齊
  • align-content——定義了多根軸線的對齊方式。如果專案只有一根軸線,該屬性不起作用

設定在專案上的屬性

  • order——定義專案的排列順序。數值越小,排列越靠前,預設為0
  • flex-grow——定義專案的放大比例,預設為0,即如果存在剩餘空間,也不放大
  • flex-shrink——定義了專案的縮小比例,預設為1,即如果空間不足,該專案將縮小
  • flex-basis——定義了在分配多餘空間之前,專案佔據的主軸空間。瀏覽器根據該屬性,計算主軸是否有多餘空間。它的預設值為auto,即專案的本來大小
  • flex——flex-growflex-shrinkflex-basis的簡寫,預設值為0 1 auto
    • 屬性有兩個快捷值:auto (1 1 auto) 和 none (0 0 auto)
  • align-self——允許單個專案有與其他專案不一樣的對齊方式,可覆蓋align-items屬性

4. 必考:BFC 是什麼?

https://segmentfault.com/a/1190000013647777

BFC的概念

塊格式化上下文(Block FormattingContext,BFC)是一個獨立的佈局環境

如果一個元素符合觸發 BFC 的條件,則 BFC 中的元素佈局不受外部影響

建立BFC

(1)根元素
(2)浮動元素float=left|right或inherit(≠none)
(3)絕對定位元素position=absolute或fixed
(4)display=inline-block|flex|inline-flex|table-cell或table-caption
(5)overflow=hidden|auto或scroll(≠visible)

BFC 的特性

  1. BFC 是一個獨立的容器,容器內子元素不會影響容器外的元素。反之亦如此
  2. 盒子從頂端開始垂直地一個接一個地排列,盒子之間垂直的間距是由 margin 決定的
  3. 在同一個 BFC 中,兩個相鄰的塊級盒子的垂直外邊距會發生重疊
  4. BFC 區域不會和 float box 發生重疊
  5. BFC 能夠識別幷包含浮動元素,當計算其區域的高度時,浮動元素也參與計算

BFC 的作用

  1. 包含浮動元素(清除浮動)

    • 浮動元素會脫離文件流(絕對定位元素也會脫離文件流),導致無法計算準確的高度,這種問題稱為高度塌陷

    • 解決高度塌陷問題的前提是能夠識別幷包含浮動元素,也就是清除浮動

    解決方法:在容器(container)中建立 BFC

  2. 避免外邊距摺疊

    外邊距摺疊(Margin collapsing)只會發生在屬於同一BFC的塊級元素之間。如果它們屬於不同的 BFC,它們之間的外邊距則不會摺疊

5. CSS 選擇器優先順序

  • 按權重和來源
    • !important——infinity
  • 按特指度排序
    • 1 0 0 0 ——行內樣式
    • 0 1 0 0—— #id
    • 0 0 1 0——.class /:偽類 / 屬性選擇器
    • 0 0 0 1—— 標籤 / 偽元素
    • 0 0 0 0—— *
    • 繼承樣式優先順序低於萬用字元選擇器樣式
  • 按前後位置排序
    • 如果兩個優先順序相同,則最後出現的優先順序高,!important也適用

(1)樣式應用時,css會先檢視規則的權重(!important),加了權重的優先順序最高,當權重相同的時候,會比較規則的特殊性

(2)特殊性值越大的宣告優先順序越高

(3)相同特殊性值的宣告,根據樣式引入的順序,後宣告的規則優先順序高(距離元素出現最近的)

6. 清除浮動說一下

https://segmentfault.com/a/1190000013664630

浮動的概念

  • 浮動的框可以向左或向右移動,直到它的外邊緣碰到包含框另一個浮動框的邊框為止
  • 由於浮動框不在文件的普通流中,所以文件的普通流中的塊框表現得就像浮動框不存在一樣

浮動的影響

浮動的清除

  1. clear屬性的空標籤

    <div class="parent">
        <div class="child">xxx</div>
        <div class="child">xxx</div>
        <div class="clearfix"></div>
    </div>
    
    .child {
      height: 100px;
      width: 100px;
      float: left;
    }
    .clearfix {
      clear: both;
    }
    
  2. 觸發BFC——父元素新增overflow:hidden

    .parent {
      overflow: hidden;
    }
    
  3. :after偽元素

    .clearfix::after {
      content: "";
      display: block;
      clear: both;
      visibility: hidden;
      height: 0;
    }
    
  4. before和after雙偽元素清除浮動

    .clearfix::before, .clearfix::after {
      content: "";
      display: table;
    }
    .clearfix::after {
      clear: both;
    }
    
  5. 父元素設定高度

    .parent {
      height: 20px;
    }
    

7.vue中APP的適配問題,使用單位

媒體查詢 @media query

  • 媒體查詢的語法
@media not|only mediatype and (expressions) {
    CSS 程式碼...;
}
  • mediaType: all | print | screen 等

  • expressions:

    • min-device-width——裝置寬度,縮放不響應
    • min-width——視口寬度,縮放響應
  • 柵格系統尺寸—elmentUI

    extra small small mediun large extra large
    <768px ≥768px ≥992px ≥1200px ≥1920px
    手機 平板 桌面顯示器 桌面顯示器 桌面顯示器
  • 使用媒體查詢

    平板背景為紅色

    @media screen (min-width: 768px) and (max-width: 882px) {
        body: {background-color: red}
    }
    

rem + 媒體查詢

rem(font size of the root element)是指相對於根元素的字型大小的單位,預設16px

螢幕劃分成多等份

  • 動態設定html標籤font-size大小

    • 假設設計稿是750px,將整個螢幕劃分成15等份, 1rem = 50px
  • 頁面元素的rem值=頁面元素值(px)/(螢幕寬度/劃分的份數)

    • 螢幕寬度/劃分的份數 為是html中的font-size的大小
  • 程式碼實現

    @media screen and (min-width:320px) {
        html {
            font-size: 50px
        }
    }
    @media screen and (min-width:640px) {
        html {
            font-size: 100px
        }
    }
    

按照縮放比例動態改變

  • 通過修改不同裝置根元素的 font-size適配

    html {
        font-size: 16px
    }
    @media screen and (min-width:768px) {
        html {
            font-size: 18px !important;
        }
    }
    @media screen and (min-width: 992px) and (max-width: 1200px){
        html {
            font-size: 20px !important;
        }
    }
    
  • setRem函式動態修改根元素 font-size

    function setRem() {
        const baseSize = 16
        //獲取螢幕寬度
        const htmlWidth = document.documentElement.clientWidth || document.body.clientWidth
      	//計算縮放比例  螢幕寬度/設計稿寬度
        let scale = htmlWidth / 1536
        //設定根元素的字型大小
        document.querySelector("html").style.fontSize = baseSize * scale + "px" 
    }
    setRem()
    window.addEventLinstence("resize", () => {
        setRem()
    })
    
  • 設定元素的寬高為 rem

    • scss

      @function px2rem($px){
        // rem基準值
        $rem : 41.4px;
        @return ($px/$rem) + rem;
      }
      
      .box{
        background-color: red;
        width: px2rem(100px);
        height: px2rem(100px);
      }
      
    • 外掛

      • px to rem ——vscode
      • postcss-pxtorem——webpack

原生 JS

1. 必考:ES 6 語法知道哪些,分別怎麼用?

  • let和const——用於宣告塊級作用域的變數且不具備變數提升

    • let 用於宣告變數
    • const 用於宣告常量,物件型別棧中的記憶體地址不可改變,可以改變堆中的值
  • 解構賦值

    • 陣列的結構賦值——陣列是按位置匹配

       let [a, b, c] = [1, 2, 3];
      
    • 物件的結構賦值——物件是按屬性名匹配

      let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
      
  • 模板字串

    • 使得字串的拼接更加的簡潔,支援變數、HTML文件與換行

      let a = "aaa"
      let b = `bbb ${a} bbb`
      
  • 箭頭函式

    • 用於簡化函式表示式和改善函式this指向的問題

      var sum = (num1, num2) => num1 + num2;
      
  • 擴充套件運算子(...)

    • 用於函式(剩餘引數)——用於獲取函式的多餘引數,不需要使用arguments物件

      function add(...values) {
        let sum = 0;
        for (var val of values) { //陣列
          sum += val;
        }
        return sum;
      }
      
    • 用於陣列或字串——將內容依次取出

      var str = "asdfghjkl"
      console.log(...str) //a s d f g h j k l
      var arr = [1,2,3,4,5,6]
      console.log(...arr) //1 2 3 4 5 6
      
    • 用於物件——克隆或者屬性拷貝

      var obj1 = { foo: 'bar', x: 42 };
      var obj2 = { foo: 'baz', y: 13 };
      var clonedObj = { ...obj1 };
      // 克隆後的物件: { foo: "bar", x: 42 }
      var mergedObj = { ...obj1, ...obj2 };
      // 合併後的物件: { foo: "baz", x: 42, y: 13 }
      
  • 類(class)

    • 讓面向物件程式設計變得更加簡單和易於理解

      class Person {
          constructor(name, age) {
              this.name = name
              this.age = age
          }
          sayHi() {
              alert(`my name is ${this.name}`)
          }
      }
      class Worker extends Person {
          constructor(name,age,job) {
              super(name,age)
              this.job = job
          }
          sayJob() {
              alert(`my job is ${this.job}`)
          }
      }
      
  • 模組化(Module)

    • 每一個模組都有自己單獨的作用域
      • 為模組創造了名稱空間,防止函式的命名衝突
    • 模組的功能主要由 export 和 import 組成
      • 通過 export 來規定模組對外暴露的介面
      • 通過import來引用其它模組提供的介面
  • Promise

    • 非同步程式設計的一種解決方案,比傳統的解決方案callback更加的優雅

    • Promise是一個容器,儲存著在某個未來結束的非同步操作的結果

    • 回撥函式

      setTimeout(function(){
          console.log('Hello'); // 1秒後輸出"Hello"
          
          setTimeout(function(){
              console.log('Hi'); // 2秒後輸出"Hi"
          }, 1000);
          
      }, 1000);
      
    • Promise

      var wait = new Promise((resolve, reject) => {
          setTimeout(resolve, 2000);
      })
      wait.then(() => console.log('Hello')).then(() => console.log('hi'))
      
  • async/await

    • async
      • 用於申明一個 function 是非同步的
      • async函式的返回值是 Promise 物件
    • await
      • 用於等待一個非同步方法執行完成
      • await 只能出現在 async 函式中
    const axios = require("axios");
    
    async function getZhihuTopSearch(id) {
      const url = "https://www.zhihu.com/api/v4/search/top_search";
      //將非同步操作的值賦給變數
      const response = await axios(url);
      console.log(response);
    }
    getZhihuTopSearch(5);
    

2. 必考 Promise、Promise.all、Promise.race 分別怎麼用?

https://www.cnblogs.com/zengbin13/p/12901561.html

Promise是非同步程式設計的一種解決方案,可以解決回撥地獄的問題。

  • Promise是一個容器,儲存著在某個未來結束的非同步操作的結果
  • Promise具有三種狀態,並且一旦狀態更改,不再變化。任何時候都可以獲得結果
    • pedding——等待狀態
    • resolved——已處理
    • rejected——已拒絕

Promise.all——同時等待多個Promise非同步操作完成以後再做某件事

Promise.race ——率先改變狀態的Promise例項作為返回值返回

3. 必考:手寫函式防抖和函式節流

https://www.cnblogs.com/zengbin13/p/12903001.html

//防抖函式
function debounce(fn, wait, immediate=true) {
    let timer, result
    return function(...args) {
        if(immediate) {
           if(!timer) {
               result = fn.apply(this, args)
           }
           timer = setTimeout(() => {
               timer = null
           }, wait)
        } else {
           if(timer) {
                clearTimeout(timer)
            }
            timer = setTimeout(() => {
                fn.apply(this, args)
            }, wait) 
        }
        return result
    }
}
//節流函式
function throttle(fn, wait = 1000) {
  let timer;
  return function (...args) {
    if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, args);
        timer = null;//到達指定時間將定時器清除,讓其能夠再次進入執行fn
      }, wait);
    }
  };
}

4. 必考:手寫AJAX

//1.建立Ajax例項
let xhr = new XMLHttpRequest();	//IE下為ActiveObject物件
//2.設定請求配置
xhr.open("GET", "data/a.text", true)
//3.事件監聽:通過監聽readyStateChange事件,獲知AJAX狀態改變 
xhr.onreadyStateChange = function() {
    //請求完成 獲取伺服器返回的響應頭響應主體
    if(xhr.readyState == 4 && xhr.status == 200 ) {
       console.log(xhr.responseText)
    }
}
//4.傳送Ajax請求
xhr.send()

5. 必考: this 的指向問題

普通函式的this

  • 函式呼叫模式
    • 如果一個函式不是一個物件的屬性時,直接作為函式來呼叫時,this 指向全域性物件
  • 方法呼叫模式
    • 如果一個函式作為一個物件的方法來呼叫時,this 指向這個物件
  • 構造器呼叫模式
    • 如果一個函式用 new 呼叫時,函式執行前會新建立一個物件,this 指向這個新建立的物件
  • apply 、call 和 bind 呼叫模式
    • 顯式地指定呼叫函式的 this 指向
函式呼叫方式 函式內部this的指向
普通函式呼叫 window
建構函式呼叫 建立的例項物件
物件方法呼叫 該方法所屬的物件
事件繫結方法 繫結事件的的物件
定時器函式 window
立即執行函式 window
匿名函式 window

箭頭函式的this

箭頭函式沒有自己的this值,箭頭函式中所使用的this都是來自函式作用域鏈,它的取值遵循普通普通變數一樣的規則,在函式作用域鏈中一層一層往上找

箭頭函式的this是繼承父執行上下文裡面的this

apply實現bind函式

https://juejin.im/post/5eb96904f265da7bac22503d#heading-9

6. 必考:閉包/立即執行函式是什麼?

https://www.cnblogs.com/zengbin13/p/12969560.html

立即執行函式

  • 立即執行函式的定義

    • 宣告一個匿名函式,馬上呼叫這個匿名函式

      (function(){alert("立即呼叫匿名函式")})()
      
  • 立即執行函式的作用

    • 建立一個獨立的作用域
    • 作用域裡面的變數,外面訪問不到(即避免「變數汙染」)
    var liList = ul.getElementsByTagName('li')
    for(var i=0; i<6; i++){
      liList[i].onclick = function(){
        alert(i) 
      }
    }
    //使用者在for迴圈完後點擊,而i貫穿作用域不是每個li都有獨立的i變數。點選時全為6
    
    var liList = ul.getElementsByTagName('li')
    for(var i=0; i<6; i++){
      !function(ii){ 
        liList[ii].onclick = function(){
          alert(ii) // 0、1、2、3、4、5
        }
      }(i)
    }
    

閉包

7. 必考:跨域的幾種實現方式

JSONP

JSONP的原理

——利用script標籤獲取資源不受到同源策略的限制。可以動態建立 script標籤,再請求一個帶參網址實現跨域通訊

//**前端程式碼** 
var script = document.createElement("script");
script.type = "text/javascript";

// 傳參並指定回撥執行函式為jsonpCallback
script.src = "http://localhost:3000?callback=jsonpCallback";
document.head.appendChild(script);

//回撥函式
function jsonpCallback(data) {
console.log(data);
}
// **後端程式碼**
const express = require('express')
const app = express()
app.get('/', (req,res) => {
    let callback = req.query.callback
    res.send(`${callback}(${JSON.stringify({
        success:0,
        data:{
            name:"xxx"
        }
    })})`)
})

app.listen(3000, () => { console.log('開啟3000埠') })

jsonp缺點

  • 需要伺服器端支援
  • 只能實現get一種請求
  • 回撥函式需要為全域性函式
  • 不安全

jQuery的封裝

$.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 請求方式為jsonp
    jsonpCallback: "jsonpCallback",    // 自定義回撥函式名
    data: {}
});

跨域資源共享 CORS

跨域資源共享(CORS) 是一種機制

使用額外的 HTTP 頭來告訴瀏覽器讓執行在一個 origin (domain) 上的Web應用被准許訪問來自不同源伺服器上的指定的資源。

當一個資源從與該資源本身所在的伺服器不同的域、協議或埠請求一個資源時,資源會發起一個跨域 HTTP 請求

  • 客戶端(傳送ajax和fetch請求)
    • 發生跨域問題時,伺服器跨域接收到請求,但是返回內容被瀏覽器遮蔽
  • 服務端設定相關的頭資訊
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*'); 
  // * 不允許攜帶cooike | 具體地址 只支援單源
  res.header('Access-Control-Allow-Headers', 
             'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
  res.header('Access-Control-Allow-Methods', 
             'PUT, POST, GET, DELETE, OPTIONS');
  //預檢請求
  if (req.method == 'OPTIONS') {
    res.send(200); //在正常的請求之前,會發送一個驗證,是否可以請求。
  }
  else {
    next();
  }
});

CORS 缺點

  • 允許源只能支援一個或全部
  • 允許全部源時,不支援攜帶cookie

http proxy (Nodejs中介軟體)

利用node + webpack + webpack-dev-server代理介面跨域。

在開發環境下,由於vue渲染服務和介面代理服務都是webpack-dev-server同一個,所以頁面與代理介面之間不再跨域,無須設定headers跨域資訊

module.exports = {
    entry: {},
    module: {},
    ...
    devServer: {
        historyApiFallback: true,
        proxy: [{
            context: '/login',
            target: 'http://www.domain2.com:8080',  // 代理跨域目標介面
            changeOrigin: true,
            secure: false,  // 當代理某些https服務報錯時用
            cookieDomainRewrite: 'www.domain1.com'  // 可以為false,表示不修改
        }],
        noInfo: true
    }
}

nginx反向代理

跨域原理

同源策略是瀏覽器的安全策略,不是HTTP協議的一部分

伺服器端呼叫HTTP介面只是使用HTTP協議,不會執行JS指令碼,不需要同源策略,也就不存在跨越問題

實現思路

通過nginx配置一個代理伺服器(域名與domain1相同,埠不同)做跳板機,反向代理訪問domain2介面,並且可以順便修改cookie中domain資訊,方便當前域cookie寫入,實現跨域登入

#proxy伺服器
server {
    listen       81;
    server_name  www.domain1.com;

    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie裡域名
        index  index.html index.htm;

        # 當用webpack-dev-server等中介軟體代理介面訪問nignx時,此時無瀏覽器參與,故沒有同源限制,下面的跨域配置可不啟用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #當前端只跨域不帶cookie時,可為*
        add_header Access-Control-Allow-Credentials true;
    }
}

postMessage跨域

postMessage是HTML5 XMLHttpRequest Level 2中的API,且是為數不多可以跨域操作的window屬性之一,它可用於解決以下方面的問題

  1. 頁面和其開啟的新視窗的資料傳遞
  2. 多視窗之間訊息傳遞
  3. 頁面與巢狀的iframe訊息傳遞
  4. 上面三個場景的跨域資料傳遞

用法

postMessage(data,origin)方法接受兩個引數
data: html5規範支援任意基本型別或可複製的物件,但部分瀏覽器只支援字串,所以傳參時最好用JSON.stringify()序列化。
origin: 協議+主機+埠號,也可以設定為"*",表示可以傳遞給任意視窗,如果要指定和當前視窗同源的話設定為"/"。

1.)a.html:(http://www.domain1.com/a.html)

<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>       
    var iframe = document.getElementById('iframe');
    iframe.onload = function() {
        var data = {
            name: 'aym'
        };
        // 向domain2傳送跨域資料
        iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
    };

    // 接受domain2返回資料
    window.addEventListener('message', function(e) {
        alert('data from domain2 ---> ' + e.data);
    }, false);
</script>

8. 常考:async/await 怎麼用,如何捕獲異常?

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

async function 宣告用於定義一個返回 AsyncFunction 物件的非同步函式。非同步函式是指通過事件迴圈非同步執行的函式,它會通過一個隱式的 Promise 返回其結果

簡單來說,如果在函式前使用async關鍵字,那麼這個函式返回一個promise。如果你返回的不是一個promise,JavaScript也會自動把這個值"包裝"成Promise的resolve值

9. 常考:如何實現深拷貝?

深拷貝和淺拷貝最根本的區別在於是否真正獲取一個物件的複製實體,而不是引用

  1. 淺拷貝的實現

    • 淺拷貝可以使用 Object.assign 和擴充套件運算子...來實現
  2. 深拷貝的實現方法

    • JSON.parse(JSON.stringify(obj))

    • 遞迴——遞迴的複製所有層級屬性

      function deepCopy(object) {
        //判斷引數是否為object
        if (!object || typeof object !== "object") return;
        let newObject = Array.isArray(object) ? [] : {};
        for (let key in object) {
          if (object.hasOwnProperty(key)) {
            newObject[key] = typeof object[key] === "object" ? 		              deepCopy(object[key]) : object[key];
          }
        }
        return newObject;
      }
      
    • jQuery的extend方法

      $.extend( [deep ], target, object1 [, objectN ] )
      

10. 常考:如何用正則實現 trim()?

String.protoType.trim = function() {
    return this.replace(/(^\s*)|(\s*$)/g, "");
}

11. 常考:不用 class 如何實現繼承?用 class 又如何實現?

ES5

//0.沒有專門的類宣告方法
function Person(name, age) {	//1.即是建構函式又是類
    this.name = name
    this.age = age
}
Person.protoType.showName = function() {	//2.方法獨立於類之外
    alert(this.name)
}
//3.沒有專門的繼承方法
function Worker(name, age, job) {
    Person.call(this, name, age) //4.從父類繼承屬性要靠騙
    this.job = job
}
Worker.prototype = new Person()	//5.沒有專門繼承父類方法的方式
Worker.prototype.constructor = Worker

ES6

class Person {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    showName() {
        alert(this.name)
    }
    showAge() {
        alert(this.age)
    }
}
class Wroker extends Person {
    constructor(name, age, job) {
        super(name, age)
  
        this.job = job
    }
    //父類的方法自動繼承
    showJob() {
        alert(this.job)
    }
}
let foo = new Worker("foo", "18", "bar")

12. 常考:如何實現陣列去重?

https://juejin.im/post/5aed6110518825671b026bed#heading-7

  1. set與解構賦值去重

    Set函式可以接受一個數組(或類陣列物件)作為引數來初始化

    function unique(arr) {
        if(!Array.isArray(arr)) {
            return new Error("type error")
        }
        return [...Set(arr)]
        //return Array.from(new Set(arr))
    }
    
  2. indexOf方法去重1

    陣列的indexOf()方法可返回某個指定的元素在陣列中首次出現的位置

    定義一個空陣列,呼叫indexOf方法對原來的陣列進行遍歷判斷,如果元素不在res中,則將其push進res中

    function unique(arr) {
        if(!Array.isArray(arr)) {
            return new Error("type error")
        }
        let res = []
        arr.forEach((item) => {
            if(res.indexOf(item) === -1) {
                res.push(item)
            }
        })
        return res
    }
    
  3. indexOf方法去重2

    function unique(arr) {
        if(!Array.isArray(arr)) {
            return new Error("type error")
        }
        return arr.filter((item, index) => {
            return arr.indexOf(item) === index
        })
    }
    
  4. 相鄰元素去重

    呼叫了陣列的排序方法sort(),然後根據排序後的結果進行遍歷及相鄰元素比對,如果相等則跳過改元素,直到遍歷結束

    function unique(arr) {
        if(!Array.isArray(arr)) {
            return new Error("type error")
        }
        arr = arr.sort()
        let res = []
        for (let i = 0; i < arr.length; i++) {
            if (arr[i] !== arr[i-1]) {
                res.push(arr[i])
            }
        }
        return res
    }
    
  5. 利用物件屬性去重

    建立空物件,遍歷陣列,將陣列中的值設為物件的屬性,並給該屬性賦初始值1,每出現一次,對應的屬性值增加1,這樣,屬性值對應的就是該元素出現的次數了

    function unique(arr) {
        if(!Array.isArray(arr)) {
            return new Error("type error")
        }
        let res = [], obj = {}
        for (let i = 0; i < arr.length; i++) {
            if (!obj[arr[i]]) {
                res.push(arr[i])
                obj[arr[i]] = 1
            } else {
                obj[arr[i]]++
            }
        }
        return res
    }
    
  6. 雙迴圈去重

    定義一個包含原始陣列第一個元素的陣列, 然後遍歷原始陣列,將原始陣列中的每個元素與新陣列中的每個元素進行比對,如果不重複則新增到新陣列中,最後返回新陣列;

    function unique(arr) {
        if(!Array.isArray(arr)) {
            return new Error("type error")
        }
        let res = [arr[0]]
        for (let i = 1; i < arr.length; i++) {
            let flag = true
            for (let j = 0; j < res.length; j++) {
                if (arr[i] === res[j]) {
                    flag = false;
                    break
                }
            }
            if (flag) {
                res.push(arr[i])
            }
        }
        return res
    }
    

13. 放棄:== 相關題目(反著答)

只用===

14. 送命題:手寫一個 Promise

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

15.建立物件的幾種實現方式

  • 工廠模式

    • 描述:使用函式抽象建立物件的細節

    • 缺點:建立的物件無法和某個類產生聯絡

      function person(name, age) {
          var obj = new Object()
          obj.name = name
          obj.age = age 
          obj.sayName = function() {
              alert(this.name)
          }
          return obj
      }
      var person1 = person("xiaoyu", 18)
      
  • 建構函式模式

    • 描述:建構函式需要使用new, new關鍵字將物件的原型指向建構函式的prototype屬性;並且將this指向新建立的物件

    • 缺點:每個建立的物件都重新開闢記憶體空間用於儲存相同的方法

      function Person(name, age) {
          this.name = name
          this.age = age 
          this.sayName = function() {
              alert(this.name)
          }
      }
      var person1 = new Person("xiaoyu", 18)
      person1.constructor = Person
      
  • 原型模式

    • 描述:使用原型物件讓所有的物件例項共享系統的屬性和方法

    • 缺點:無法為物件設定初始值

      function Person() {
      }
      Person.protoType = {
          name: "xiaoyu",
          age: 18,
          sayName: function() {
              alert(this.name)
          }
      }
      var person1 = new Person()
      
  • 建構函式 + 原型

    • 描述:建構函式模式 與 原型模式相結合
    • 缺點:兩種模式相結合 程式碼封裝性不好
    function Person(name, age){
        this.name = name;
        this.age = age;
    }
    Person.prototype = {
        constructor: Person,
        sayName: function(){
            alert(this.name);
        }
    }
    var person1 = new Person("xiaoyu", 18)
    
  • 動態原型模式

    function Person(name, age){
        this.name = name;
        this.age = age;
        if(typeof this.sayName !== "function" ){
            Person.prototype.sayName = function(){
                alert(this.name);
            } 
        } 
    }
    
    var person1 = new Person("xiaoyu", 18)
    
  • 寄生建構函式模式

    function Person(name, age) {
        var obj = new Object()
        obj.name = name
        obj.age = age 
        obj.sayName = function() {
            alert(this.name)
        }
        return obj
    }
    var person1 = new Person("xiaoyu", 18)
    

16.繼承的幾種實現方式

繼承是面嚮物件語言中最重要的一個概念。由於在 JavaScript 中函式沒有簽名,無法實現介面繼承,只支援實現繼承

  • 原型鏈

    • 缺點:屬性被例項共享;不能向父類傳遞引數
    function Parent() {}
    function Child() {}
    Child.prototype = new Parent()
    
  • 借用建構函式(經典繼承)

    • 優點:避免屬性共享;可以向父類傳參
    • 缺點:方法建構函式中定義,建立例項都會建立一次
    function SuperType(name){
        this.name = name
        this.colors = ["red", "blue", "green"];
    }
    function SubType(name){
        //繼承了 SuperType
        SuperType.call(this, name);
    }
    var instance1 = new SubType();
    instance1.colors.push("black");
    console.log(instance1.colors);  //"red,blue,green,black"
    var instance2 = new SubType();
    console.log(instance2.colors);  //"red,blue,green"
    
  • 組合繼承

    • 描述:使用原型鏈實現對原型屬性和方法的繼承,而通過借用建構函式來實現對例項屬性的繼承
    • 缺點:呼叫兩次父類建構函式
    function SuperType(name){
        this.name = name
        this.colors = ["red", "blue", "green"];
    }
    SuperType.prototype.sayName = function(){
        console.log(this.name);
    }
    function SubType(name, age){
        //繼承屬性
        SuperType.call(this,name);
        this.age = age;
    }
    //繼承方法
    SubType.prototype = new SuperType();
    SubType.prototype.constructor = SubType;
    SubType.prototype.sayAge = function(){
        console.log(this.age);
    }
    
    var instance1 = new SubType("james",9);
    instance1.colors.push("black");
    console.log(instance1.colors);  //"red,blue,green,black"
    instance1.sayName(); // "james"
    instance1.sayAge(); // 9
    
    var instance2 = new SubType("kobe",10);
    console.log(instance2.colors);  //"red,blue,green"
    instance2.sayName(); // "kobe"
    instance2.sayAge(); // 10
    
  • 原型式繼承(Object.create())

    function object(o){
        function F(){};
        F.prototype = o;
        return new F();
    }
    

DOM

1. 必考:事件委託

事件委託本質

  • 利用瀏覽器事件冒泡的機制——父級元素可以通過事件物件獲取到觸發事件的目標節點,因此可以由父級元素統一監聽和處理多個子元素的事件

事件委託的優點

  • 不必為每一個子元素都繫結一個監聽事件
  • 減少記憶體的消耗
  • 實現事件的動態繫結——比如新增子節點

2. 曾考:用 mouse 事件寫一個可拖曳的 div

 var box = document.querySelector("#box")
  var position = null;
  var dragging = false;
  box.addEventListener("mousedown", function (e) {
    dragging = true;
    position = [e.clientX, e.clientY];  //獲取座標
  });

  document.addEventListener("mousemove", function (e) {
    if (dragging === false) return;
    //獲取現在的座標
    const x = e.clientX;
    const y = e.clientY;
    //位移: 當前座標 - 位置資訊
    const deltaX = x - position[0];
    const deltaY = y - position[1];
    //移動
    const left = parseInt(box.style.left) || 0;
    const top = parseInt(box.style.top) || 0;
    box.style.left = left + deltaX + "px";
    box.style.top = top + deltaY + "px";
    //儲存現在座標作為位置資訊
    position = [x, y];
  });

  document.addEventListener("mouseup", function (e) {
    dragging = false;
  });

HTTP

1. 必考:HTTP 狀態碼知道哪些?分別什麼意思?

1XX Informational (資訊性狀態碼)

表示臨時響應並需要請求者繼續執行操作的狀態碼

  • 100 Continue 繼續

  • 請求者應當繼續提出請求。伺服器返回此程式碼表示已收到請求的第一部分,正在等待其餘部分

  • 101 Switching Protocols 切換協議

    • 請求者已要求伺服器切換協議,伺服器已確認並準備切換

2XX Success(成功狀態碼)

表示成功處理了請求的狀態碼

  • 200 OK 成功

    • 客戶端傳送的請求在伺服器端正常處理

    GET 方法——對應請求資源的實體會作為響應返回
    HEAD方法——在響應中只返回首部,不會返回實體的主體部分

  • 201 Created 已建立

    • 請求成功並且伺服器建立了新的資源
  • 202 Accepted 已接受

    • 伺服器已接受請求,但尚未處理或稍後處理
  • 203 Non-Authoritative Information 非授權資訊

    • 伺服器已經成功處理了請求,但返回的資訊可能來自另一來源
  • 204 No Content 無內容

    • 伺服器成功處理了請求,但沒有返回任何內容
  • 205 Reset Content 重置內容

    • 伺服器成功處理了請求,但沒有返回任何內容
    • 與204類似,表明客戶端應重置資料來源的檢視或資料結構
  • 206 Partial Content 部分內容

    • 伺服器成功處理了部分GET請求。常用於大型二進位制檔案的斷點續傳

3XX Redirection(重定向狀態碼)

需要進行附加操作以完成請求

  • 300 Multiple Choices 多重選擇

    • 針對請求,伺服器可執行多種操作。伺服器可根據請求者(user agent)選擇一項操作,或提供操作列表供請求者選擇
  • 301 Moved Permanently 永久移動

    • 請求的網頁已永久移動到新位置。伺服器返回此響應(對GET或HEAD請求的響應)時,會自動將請求者轉到新位置
  • 302 Found 臨時移動

    • 伺服器目前從不同位置的網頁響應請求,但請求者應繼續使用原有位置來進行以後的請求
  • 303 See Other 檢視其它位置

    • 請求者應當對不同的位置使用單獨的GET請求來檢索響應時,伺服器返回此程式碼

    請求已經被處理,但伺服器不是直接返回一個響應文件,而是返回一個響應文件的URI

  • 304 Not Modified 未修改

    • 自動上次請求後,請求的網頁未修改過。伺服器返回此響應,不會返回網頁的內容
  • 305 Use Proxy 使用代理

    • 請求者只能使用代理訪問請求的網頁。如果伺服器返回此響應,還表示請求者應使用代理
  • 307 Temporary Redirect 臨時重定向

    • 伺服器目前從不同位置的網頁響應請求,但請求者應繼續使用原有的位置來進行以後的請求

    伺服器尚未執行操作,客戶端需要向Location報頭裡的那個URI重新提交整個請求

4XX Client Error(客戶端錯誤狀態碼)

表示請求可能出錯,妨礙了伺服器的處理

  • 400 Bad Request 錯誤請求

    • 伺服器不理解請求的語法
  • 401 Unauthorized 未授權

    • 請求要求身份驗證。對於需要登入的網頁,伺服器可能返回此響應
  • 403 Forbidden 禁止

    • 伺服器拒絕請求
  • 404 Not Found 未找到

    • 伺服器找不到請求的網頁
  • 405 Method Not Allowd 方法禁用

    • 禁用請求中指定的方法

    客戶端試圖使用一個本資源不支援的HTTP方法

  • 406 Not Acceptable 不接受

    • 無法使用請求的內容特性響應請求的網頁
  • 407 Proxy Authentication Required需要代理身份驗證

    • 此狀態碼與401(未授權)類似,但指定請求者應當授權使用代理
  • 408 Reqeust Timeout 請求超時

    • 伺服器等候請求時發生超時
  • 409 Conflict 衝突

    • 伺服器在完成請求時發生衝突。伺服器必須在響應中包含有關衝突的資訊

5XX Server Error(伺服器錯誤狀態碼)

表示伺服器在嘗試處理請求時發生內部錯誤

  • 500 Internal Server Error 伺服器內部錯誤
    • 伺服器遇到錯誤,無法完成請求
  • 503 Service Unavailable 伺服器不可用
    • 伺服器目前無法使用(由於超載或者停機維護)。通常只是暫時狀態

https://juejin.im/entry/586b5b7dac502e12d62b4f33

2. 大公司必考:HTTP 快取有哪幾種?

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

HTTP 快取分為 2 種,一種是強快取,另一種是協商快取

主要作用是可以加快資源獲取速度,提升使用者體驗,減少網路傳輸,緩解服務端的壓力

3. 必考:GET 和 POST 的區別

GET和POST本質上兩者沒有任何區別。都是HTTP協議中的請求方法底層實現都是基於TCP/IP協議。

所謂區別,只是瀏覽器廠家根據約定,做出的限制

  • 用法方面
    • GET一般用於請求資料,POST用於提交資料
  • 引數方面
    • GET引數通過URL傳遞,POST放在Request body中
    • GET請求在URL中傳送的引數是有長度限制的(2k),而POST沒有
    • GET請求引數只能是ASCII碼而中文需要URL編碼,而POST支援多種編碼方式
    • GET比POST更不安全,因為引數直接暴露在URL上,所以不能用來傳遞敏感資訊
  • 瀏覽器行為方面
    • GET產生的URL地址可以被Bookmark,而POST不可以
    • GET請求會被瀏覽器主動cache,而POST不會,除非手動設定
    • GET請求引數會被完整保留在瀏覽器歷史記錄裡,而POST中的引數不會被保留
    • GET在瀏覽器回退時是無害的,而POST會再次提交請求
  • 資料包方面
    • GET產生一個TCP資料包;POST產生兩個TCP資料包
      • 對於GET方式的請求,瀏覽器會把http header和data一併傳送出去,伺服器響應200(返回資料)
      • 對於POST,瀏覽器先發送header,伺服器響應100 continue,瀏覽器再發送data,伺服器響應200 ok(返回資料)

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

https://www.bilibili.com/video/BV1ut411j7R7?from=search&seid=6592752127117987191

cookie localStorage sessionStorage
共同點 鍵值對形式儲存
同域名可用
同上 同上
儲存位置 客戶端 同上 同上
生命週期 可設定失效時間,預設關閉瀏覽器後失效 手動清除,否則將會永久儲存 僅在當前網頁會話下有效,關閉頁面或瀏覽器後就會被清除
資料大小 4KB 5MB 同上
http請求 隨請求頭提交 不參與和伺服器的通訊 不參與和伺服器的通訊
跨頁 可跨頁
不可跨域
同上 不可跨頁
不可跨域
易用性 自行封裝介面 易用介面 同上

Session

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

5.HTTP1和HTTP2的區別

https://segmentfault.com/a/1190000019521772

http1.0特性

  • 無狀態:伺服器不跟蹤不記錄請求過的狀態
    • 藉助cookie/session機制來做身份認證和狀態記錄
  • 無連線:瀏覽器每次請求都需要建立tcp連線
    • 效能缺陷
      • 無法複用連線:每次請求都需進行一次tcp連線(3次握手4次揮手),網路利用率低
      • 隊頭阻塞:http1.0規定在前一個請求響應到達之後下一個請求才能傳送,如果前一個阻塞,後面的請求也給阻塞的

http1.1特性

  • 長連線

    • 新增Connection欄位,可以設定keep-alive值保持連線
    • http1.1預設保持長連線,資料傳輸完成保持tcp連線不斷開
  • 管道化

    • 基於長連線,可以一次傳送多個請求,響應仍按請求順序返回

      //非管道化
      請求1 > 響應1 --> 請求2 > 響應2 --> 請求3 > 響應3
      //管道化
      請求1 --> 請求2 --> 請求3 > 響應1 --> 響應2 --> 響應3
      
  • 快取處理

    • 當瀏覽器請求資源時,先看是否有快取的資源,如果有快取,直接取,不會再發請求,如果沒有快取,則傳送請求
    • 通過設定欄位cache-control來控制
  • 斷點傳輸

http2.0特性

  • 二進位制分幀
    • 將所有傳輸的資訊分割為更小的訊息和幀,並對它們採用二進位制格式的編碼
  • 多路複用
  • 頭部壓縮
  • 伺服器推送
    • 伺服器可以額外的向客戶端推送資源,而無需客戶端明確的請求

6. 從輸入URL到頁面載入發生了什麼?

  1. 位址列輸入URL並按下回車

  2. DNS解析:將輸入的URL找到對應的IP地址

    • DNS快取:瀏覽器 -> 作業系統
      • 瀏覽器會在快取中查詢URL是否存在,並比較快取是否過期
      • win作業系統儲存在 C:\Windows\System32\drivers\etc
    • 分級查詢
      • 本地DNS伺服器 ->根域名伺服器 ->COM頂級域名伺服器
  3. 建立TCP連線(三次握手)

    • 第一次握手:客戶端傳送 SYN=1欄位和客戶端序列號 seq=n,並進入SYN_SENT狀態,等待伺服器確認;
    • 第二次握手: 伺服器收到客戶端的SYN欄位,返回 SYN=1表示同意建立連線 ack=n+1用於確定收到客戶端資訊和服務端本身的序號 seq=x,此時伺服器進入SYN_RECV狀態;
    • 第三次握手:客戶端收到伺服器的SYN+ACK包,向伺服器傳送確認包 ack=x+1,此包傳送完畢,客戶端和伺服器進入ESTABLISHED(TCP連線成功)狀態,完成三次握手
    客戶端 -> 服務端:SYN=1(請求進行連線) seq=n(序列號)
    服務端 -> 客戶端:SYN=1(同意建立連線) ack=n+1(確認收到資訊) seq=x(服務端序列號)
    客戶端 -> 服務端:SYN=0(開始傳送資訊) ack=x+1(確認收到資訊) seq=n+1
    
  4. 客戶端傳送HTTP請求

    • tcp將http請求報文切割為報文段,並在各個報文上打上標記序號以及埠號,將每個報文段可靠地傳給網路層
    • 協議在網路層通過ip地址找到mac地址(ARP協議,解析地址,根據通訊方的ip地址反查出對應的MAC地址),在各個路由中間進行路由中轉傳送到資料鏈路層
    • 伺服器端在資料鏈路層收到資料,按資料鏈路層→網路層→傳輸層→應用層順序逐層傳送資料,期間,之前加在資料報上的報頭資訊被層層解析丟棄
  5. 服務端接收HTTP請求,並返回HTML響應報文

  6. 客戶端解析響應資料,佈局與渲染頁面

  7. 斷開連線(四次揮手)

7.http和https有什麼區別?

HTTP協議本身明文傳輸,導致在傳輸過程中很容易被擷取和篡改資料。因此HTTP協議不適合傳輸如支付密碼等敏感資訊。

HTTPS在HTTP的基礎上加入SSL協議依賴證書驗證伺服器的身份,實現瀏覽器和服務端的加密通訊

區別

  • http是超文字傳輸協議,資料通過明文傳輸;https協議基於ssl加密傳輸的更加安全
  • http速度更快,https傳輸需要驗證證書
  • 埠不同,http埠是80,https埠是443
  • http連線是無狀態的

8.三次握手和四次揮手

https://www.bilibili.com/video/BV1vA411i7rs

三次握手

  • 第一次握手:客戶端傳送 SYN=1欄位和客戶端序列號 seq=n,並進入SYN_SENT狀態,等待伺服器確認;
  • 第二次握手: 伺服器收到客戶端的SYN欄位,返回 SYN=1表示同意建立連線 ack=n+1用於確定收到客戶端資訊和服務端本身的序號 seq=x,此時伺服器進入SYN_RECV狀態;
  • 第三次握手:客戶端收到伺服器的SYN+ACK包,向伺服器傳送確認包 ack=x+1,此包傳送完畢,客戶端和伺服器進入ESTABLISHED(TCP連線成功)狀態,完成三次握手
客戶端 -> 服務端:SYN=1(請求進行連線) seq=n(序列號)
服務端 -> 客戶端:SYN=1(同意建立連線) ack=n+1(確認收到資訊) seq=x(服務端序列號)
客戶端 -> 服務端:SYN=0(開始傳送資訊) ack=x+1(確認收到資訊) seq=n+1

四次揮手

https://www.bilibili.com/video/BV1C5411Y7dG

  • 第一次揮手:客戶端傳送 Fin=1表示將要關閉連線,客戶端進入 FIN_WAIT_1狀態
  • 第二次揮手:服務端傳送確認應答報文 ack=n+1和服務端序列號 seq=x,告知對方知道要關閉連線,但要等待資料處理完成。服務端進行 close_wait狀態,客戶端收到報文進入FIN_WAIT_2狀態
  • 第三次揮手:當服務端處理完資料,傳送 Fin=1報文告知客戶端已經處理完資料可以關閉連線,服務端進入 LAST_ACK狀態
  • 第四次揮手:客戶端收到 FIn報文,傳送 ACK報文進入 TIME_WAIT狀態
客戶端 -> 服務端:Fin=1(關閉連線) ack=x+1(確定身份) seq=n(序列號)
服務端 -> 客戶端:ack=n+1(確認收到資訊) seq=x(服務端序列號)
服務端 -> 客戶端:Fin=1(關閉連線) ack=n seq=x(服務端序列號)
客戶端 -> 服務端: ack=x+1(確認收到資訊) seq=n

框架 Vue

1. 必考:watch 和 computed 和 methods 區別是什麼?

methods

  • 作用

    • 在Vue中定義函式方法,可以對DOM發生的事件作出反應
  • 使用

    • 使用 v-on指令繫結事件處理函式
    <button @click="handleSubmit">Submit</button>
    
    methods: {
        handleSubmit() {}
      }
    

computed(計算屬性)

  • 作用

    • 在Vue中替代具有複雜邏輯的模板表示式
  • 使用

    • get方法返回計算後的值, 計算屬性被賦值時呼叫set方法
    <p>name: {{ fullName }}</p>
    
    // ...
    computed: {
      fullName: {
        // getter
        get: function () {
          return this.firstName + ' ' + this.lastName
        },
        // setter
        set: function (newValue) {
          var names = newValue.split(' ')
          this.firstName = names[0]
          this.lastName = names[names.length - 1]
        }
      }
    }
    // ...
    
  • 特點

    • 支援快取
      • methods可以實現computed相同功能,但是不支援快取
      • 僅當依賴資料傳送改變時才會重新計算;
      • 頁面重新渲染時,依賴資料未改變不會重新計算
    • 不支援非同步
      • 內部的非同步操作無效,無法監聽資料的變化
  • 使用場景

    • 一個數據受多個數據影響
    • 簡化tempalte裡面{{}}計算和處理props或$emit的傳值

watch(偵聽屬性)

  • 作用
    • 在Vue中資料變化時處理執行非同步開銷較大的操作時
  • 特點
    • 不支援快取
      • 頁面重新渲染時值不變化也會執行
      • 直接監測一個值的變化情況,不會像computed檢測其中的依賴
    • 支援非同步操作
    • 引數
    • watch裡面的函式接收兩個值。分別為變化前和變化後的值
  • 使用場景
    • 資料變化響應時,執行非同步操作,或高效能消耗的操作
    • 一個數據影響多個
    • 監聽props,$emit或本元件的值執行非同步操作

2.v-for渲染列表中 key的作用

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

主要是為了高效的更新虛擬DOM, 新增key作為唯一標識能夠讓Diff演算法正確識別節點並且插入到正確位置

渲染專案列表時,key 屬性允許 Vue 跟蹤每個 Vnode。key 值必須是唯一的

  1. vue中預設使用“就地更新”的策略,不同的 key屬性的元素將不會被複用

  2. v-for中使用key與虛擬dom和diff演算法有關,每個節點帶有唯一標識,Diff演算法正確識別此節點

3. 必考:Vue 有哪些生命週期鉤子函式?分別有什麼用?

4. 必考:Vue 如何實現元件間通訊?

5. 必考:Vue 資料響應式怎麼做到的?

6. 必考:Vue.set 是做什麼用的?

Vue 不能檢測到物件屬性的新增或刪除,解決方法是手動呼叫 Vue.set 或者 this.$set

7. Vuex 你怎麼用的?

8. VueRouter 你怎麼用的?

9. 路由守衛是什麼?

10.keep-alive的用處

框架 React

  1. 必考:受控元件 V.S. 非受控元件
  2. 必考:React 有哪些生命週期函式?分別有什麼用?(Ajax 請求放在哪個階段?)
  3. 必考:React 如何實現元件間通訊?
  4. 必考:shouldComponentUpdate 有什麼用?
  5. 必考:虛擬 DOM 是什麼?
  6. 必考:什麼是高階元件?
  7. React diff 的原理是什麼?
  8. 必考 Redux 是什麼?
  9. connect 的原理是什麼?

TypeScript

  1. never 型別是什麼?
  2. TypeScript 比起 JavaScript 有什麼優點?

Webpack

https://zhuanlan.zhihu.com/p/44438844

必考:有哪些常見 loader 和 plugin,你用過哪些?

英語題:loader 和 plugin 的區別是什麼?

必考:如何按需載入程式碼?

必考:如何提高構建速度?

轉義出的檔案過大怎麼辦?

安全

  1. 必考:什麼是 XSS?如何預防?
  2. 必考:什麼是 CSRF?如何預防?

開放題目

  1. 必考:你遇到最難的問題是怎樣的?
  2. 你在團隊的突出貢獻是什麼?
  3. 最近在關注什麼新技術
  4. 有沒有看什麼原始碼,看了後有什麼記憶深刻的地方,有什麼收穫

刁鑽題目

  1. 程式碼
  2. 程式碼
  3. (a ==1 && a== 2 && a==3) 可能為 true 嗎?

超綱題

  1. JS 垃圾回收機制

  2. Eventloop 說一下

個性化題目

  • PWA
  • echarts.js / d3.js
  • three.js
  • flutter
  • SSR