写给自己看的面试题整理-算法&某东笔试题

写给自己看的面试题整理-算法&某东笔试题

  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
    复制代码

转载于:https://juejin.im/post/5c765e1d518825407a32b3ba

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值