寫給自己看的面試題整理-演算法&某東筆試題

瓜坤發表於2019-02-27

寫給自己看的面試題整理-演算法&某東筆試題

  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. 手寫 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
    複製程式碼

相關文章