<strike id="cy2gs"><menu id="cy2gs"></menu></strike>
  • <del id="cy2gs"><dfn id="cy2gs"></dfn></del>
  • 死磕javascript的手寫面試題

    2021-4-15    前端達人

    1.實現(xiàn)lodash的_.get方法

    function _getValue(target, valuePath, defalutVal) {
      let valueType = Object.prototype.toString.call(target)
      console.log(valueType)
      // if (valueType == "[object Array]") {
        let paths = valuePath.replace(/\[(\d+)\]/, `.$1`).split('.')
        let result = target
        for(const path of paths){
          result = Object(result)[path]
          if(result == undefined){
            return defalutVal
          }
        }
        return result
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    測試:
    let obj = {
      a:{
        b:[
          {
            c:2
          }
        ]
      }
    }
    
    console.log(_getValue(obj, 'a.b[0].c')) //2 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.寫一個函數(shù)判斷兩個變量是否相等

    function isEqual(res1, res2) {
      let a = getTypeOf(res1)
      let b = getTypeOf(res2)
      if(a !== b){
        return false
      }else if(a === 'base'){
        console.log('base',res1,res2)
        return res1 === res2
      } else if(a === 'array'){
        if(res1.length !== res2.length){
          console.log('array',res1,res2)
          return false
        }else{
          //遍歷數(shù)組的值比較
          for(let i =0;i<res1.length;i++){
            if(!isEqual(res1[i],res2[i])){
              console.log('array',res1[i],res2[i])
              return false
            }
          }
          return true
        }
        return true
      }else if(a === 'object'){
        let ak = Object.keys(a)
        let bk = Object.keys(b)
        if(ak.length !== bk.length){
          return false
        }else{
          for(let o in res1){
            console.log(res1[o])
            if(!isEqual(res1[o],res2[o])){
              console.log('object',res1[o],res2[o])
              return false
            }
          }
          return true
        } 
      }else if(a === 'null' || a === 'undefined'){
        console.log('null')
        return true
      }else if(a === 'function'){
        console.log('function')
        return a === b
      }
    }
    
    function getTypeOf(res) {
      let type = Object.prototype.toString.call(res)
      switch (type) {
        case "[object Array]":
          return 'array'
        case "[object Object]":
          return 'object'
        case "[object Null]":
          return 'null'
        case "[object Undefined]":
          return 'undefined'
        case "[object Number]"||"[object String]"||"[object Boolean]":
          return 'base'
        case "[object Function]":
          return 'function'
        default:
          return 'typeError'
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    測試:
    let a = {
      a:20,
      b:{
        c:30,
        d:[1,2,3]
      }
    }
    let b = {
      a:20,
      b:{
        c:30,
        d:[1,2,3]
      }
    }
    console.log(isEqual(a,b)) //true 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.數(shù)組扁平化的方法

    function _flat(arr){
      let result = []
      for(let i = 0;i<arr.length;i++){
        if(Array.isArray(arr[i])){
          result = result.concat(_flat(arr[i]))
        }else{
          result.push(arr[i])
        }
      }
      return result;
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    let arr = [1,2,[3,4,[5,6]]]
    _flat(arr) //[1,2,3,4,5,6] 
    
    • 1
    • 2
    //es6
    function _flat2(arr){
      while(arr.some(item=>Array.isArray(item))){
        arr = [].concat(...arr)
      }
      return arr
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    let arr = [1,2,[3,4,[5,6]]]
    _flat2(arr) //[1,2,3,4,5,6] 
    
    • 1
    • 2

    4.深克隆

    簡單深克隆,不考慮內(nèi)置對象和函數(shù)

    function deepClone(obj){
      if(typeof obj !== 'object') return
      let newObj = obj instanceof Array?[]:{}
      for(let key in obj){
          if(obj.hasOwnProperty(key)){
              newObj[key] = typeof obj[key] === 'object'?deepClone(obj[key]):obj[key]
          }
      }
      return newObj
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    復雜版深度克隆 考慮內(nèi)置對象 比如date regexp 函數(shù) 以及對象的循環(huán)引用的問題

    const isObject = (target) => typeof target === "object"&& target !== null;
    
    function deepClone2(target, map = new WeakMap()) {
      console.log(target)
        if (map.get(target)) {
            return target;
        }
        // 獲取當前值的構(gòu)造函數(shù):獲取它的類型
        let constructor = target.constructor;
        // 檢測當前對象target是否與正則、日期格式對象匹配
        if (/^(RegExp|Date)$/i.test(constructor.name)) {
            // 創(chuàng)建一個新的特殊對象(正則類/日期類)的實例
            return new constructor(target);  
        }
        if (isObject(target)) {
            map.set(target, true);  // 為循環(huán)引用的對象做標記
            const cloneTarget = Array.isArray(target) ? [] : {};
            for (let prop in target) {
                if (target.hasOwnProperty(prop)) {
                    cloneTarget[prop] = deepClone(target[prop], map);
                }
            }
            return cloneTarget;
        } else {
            return target;
        }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    5.數(shù)組去重

    filter去重

    function _unique(arr){
      return arr.filter((item,index,array)=>{
        return array.indexOf(item) === index
      })
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    es6 Set

    function _unique2(arr){
      return [...new Set(arr)]
    } 
    
    • 1
    • 2
    • 3

    includes

    function _unique3(arr){
      let newArr = []
      arr.forEach(item => {
          if(!newArr.includes(item)){
            newArr.push(item)
          }
      });
      return newArr
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    雙層for循環(huán)

    function _unique4(arr){
      for(let i =0;i<arr.length;i++){
        for(let j =i+1;j<arr.length;j++){
          if(arr[i] === arr[j]){
            arr.splice(j,1)
            j--
          }
        }
      }
      return arr
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    indexof

    function _unique5(arr){
      let newArr = []
      for(let i = 0;i<arr.length;i++){
        if(newArr.indexOf(arr[i] === -1){
          newArr.push(arr[i])
        })
      }
      return newArr
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6.判斷數(shù)據(jù)的類型

    function _typeOf(obj){
      let res = Object.prototype.toString.call(obj).split(' ')[1]
      let mold = res.substring(0,res.length-1).toLowerCase()
      return mold
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    _typeOf(5) //number
    _typeOf('5') //string 
    
    • 1
    • 2

    7.解析url參數(shù)為對象

    function getParamsObj(params){
      let paramsStr = params.replace(/^.+\?(.+)/,"$1")
      let paramsArr = paramsStr.split('&')
      let paramsObj = {}
    
      for(let [key,value] of paramsArr.entries()){
          if(/=/.test(value)){
              let valArr = value.split('=')
              val = decodeURIComponent(valArr[1]) //解碼
              val = /^\d+$/.test(val)?parseFloat(val):val //判斷是不是數(shù)字
              if(paramsObj.hasOwnProperty(valArr[0])){
                  paramsObj[valArr[0]] = [].concat(paramsObj[valArr[0]],val)
              }else{
                  paramsObj[valArr[0]] = val
              }
          }  
    
      }
      return paramsObj
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    8.函數(shù)柯里化

    //從一次傳入多個參數(shù)  編程多次調(diào)用每次傳入一個參數(shù)
    function add(a, b, c, d, e) {
      return a + b + c + d + e
    }
    
    function curry(fn) {
       let dFn = (...args)=>{
         if(args.length == fn.length) return fn(...args)
         return (...arg)=>{
           return dFn(...args,...arg)
         }
       }
       return dFn
    }
    let addCurry = curry(add)
    addCurry(1,2,3)(2)(3) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    9.圖片懶加載

    //添加了兩個功能
    // 圖片加載完成后 移除事件監(jiān)聽
    // 加載完的圖片從imgList中移除
    let imgList = [...document.querySelectorAll('img')]
    let length = imgList.length
    
    const imgLazyLoad = function () {
      let count = 0
      let deleteIndexList = []
      imgList.forEach((img, index) => {
        let rect = img.getBoundingClientRect() 
        //獲取元素到視圖的距離 top元素上邊到視圖上邊的距離 left元素左邊到視圖左邊的距離  right... bottom...
        if (rect.top < window.innerHeight) {
          // img.src = img.dataset.src
          img.src = img.getAttribute('data-src')
          deleteIndexList.push(index)
          count++
          if (count === length) {
            document.removeEventListener('scroll', imgLazyLoad)
          }
        }
      })
      imgList = imgList.filter((img, index) => !deleteIndexList.includes(index))
    }
    imgLazyLoad()
    
    document.addEventListener('scroll', imgLazyLoad) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    圖片懶加載:https://juejin.cn/post/6844903856489365518#heading-19

    10節(jié)流防抖

    函數(shù)防抖 觸發(fā)高頻事件 事件在n后執(zhí)行,如果n秒鐘重復執(zhí)行了 則時間重置

    //簡易版
    function debounce(func,wait){
      let timer; 
      return function(){
        let context = this;
        let args = arguments;
        console.log(timer)
        clearTimeout(timer)
        timer = setTimeout(function(){
          func.apply(context,args)
        },wait)
      }
    
    }
    let btn = document.querySelector('button');
    function aa(){
      console.log(111)
    }
    btn.onclick = debounce(aa,2000) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    // 復雜版
    // 1.取消防抖  
    // 2.立即執(zhí)行功能(點擊之后立即執(zhí)行函數(shù)  但是 wait時間之后在點擊才能在立即執(zhí)行)  
    // 3.函數(shù)可能有返回值
    function debounce(func,wait,immediate){
      let timer,result;
    
      const debounce = function () {
        const context = this
        const args = arguments
    
        if(timer) clearTimeout(timer)
        if(immediate){
          console.log(timer)
          var callNow = !timer
          timer = setTimeout(function () {
              timer =null
          },wait)
          if(callNow) result = func.apply(context,args)
        }else{
          timer = setTimeout(function (params) {
            result = func.apply(context,args)
          },wait)
        }
        return result
      }
    
      debounce.cance = function () {
        clearTimeout(timer)
        timer=null
      }
    
      return debounce
    
    }
    
    let btn = document.querySelector('button');
    function aa(){
      console.log(111)
    }
    btn.onclick = debounce(aa,2000,true)``` 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    函數(shù)節(jié)流 觸發(fā)高頻事件 且n秒只執(zhí)行一次

    //使用時間戳
    function  throttle(func,wait) {
      var context,args;
      var previous = 0
    
      return function () {
        context = this;
        args = arguments;
        let nowDate = +new Date()
        if(nowDate-previous>wait){
          func.apply(context,arguments)
          previous = nowDate
        }
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    //定時器
    function throttle(func,wait) {
      var context,args;
      var timer;
      return function(){
        context = this;
        args = arguments;
        if(!timer){
          timer = setTimeout(function () {
            timer = null;
            func.apply(context,args)
          },wait)
        }
      }
    
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    //組合版 options.leading 為true 立即執(zhí)行一次 options.trailing為true  結(jié)束之后執(zhí)行一次 默認為true
    function throttle(func, wait ,options = {}) {
      var context, args, timer,result;
      var previous = 0;
    
      var later = function () {
        previous = options.leading === false ? 0 : new Date().getTime();
        timer = null;
        func.apply(context, args)
        if (!timer) context = args = null;
      }
    
      var throttle = function () {
        var now = new Date().getTime()
        if (!previous && options.leading === false) previous = now;
        context = this;
        args = arguments;
    
        //下次觸發(fā) func 剩余的時間
        var remaining = wait - (now - previous);
        if (remaining <= 0 || remaining > wait) {
          // if (timer) {
          //   clearTimeout(timer);
          //   timer = null;
          // }
          previous = now;
          func.apply(context, args);
          if (!timer) context = args = null;
        } else if (!timer&& options.trailing !== false) {
          timer = setTimeout(later, remaining);
        }
      }
    
      throttled.cancel = function() {
        clearTimeout(timer);
        previous = 0;
        timer = null;
      }
    
      return throttle
    }
    
    function aa(e) {
      console.log(111)
      console.log(e)
    }
    
    let btn = document.querySelector('button');
    btn.onclick = throttle(aa, 2000,{
      leading:false,
      trailing:true 
    

    })

    轉(zhuǎn)自:csdn論壇 作者:Selfimpr歐

    日歷

    鏈接

    個人資料

    藍藍設計的小編 http://www.skdbbs.com

    存檔

    主站蜘蛛池模板: 色偷偷88欧美精品久久久| 中文字幕av日韩精品一区二区| 久久久国产精品| 国产精品99久久久久久人| 国产香蕉国产精品偷在线观看 | 亚洲精品无码久久久久去q | 国产精品无码不卡一区二区三区| 91探花国产综合在线精品| 中文字幕一精品亚洲无线一区 | 98香蕉草草视频在线精品看| 精品亚洲aⅴ在线观看| 拍国产乱人伦偷精品视频 | 成人午夜精品亚洲日韩| 91精品国产高清久久久久久91| 亚洲AV永久无码精品| 精品亚洲视频在线观看| 日本精品一区二区三区在线观看| 精品国产精品国产偷麻豆| 无码人妻精品中文字幕免费 | 国产欧美精品一区二区三区四区| 精品一区二区在线观看| 国产精品日本一区二区不卡视频 | 九九热在线精品视频| 国产精品三级在线观看无码| 亚洲爆乳精品无码一区二区三区| 四虎精品免费永久免费视频| 精品人妻少妇嫩草AV无码专区| 久久亚洲精品视频| 国产精品亚洲专区在线观看| 99精品国产一区二区三区| 国产精品亚洲A∨天堂不卡| 国产亚洲欧美精品永久| 国产精品国色综合久久| 97久久精品午夜一区二区| 精品无码AV无码免费专区| 青草国产精品久久久久久| 亚洲精品无码乱码成人 | 99热热久久这里只有精品68| 欧美精品1区2区| 久久最新精品国产| 一区二区三区四区精品视频|