前端常见编程题

173 阅读2分钟

1. 防抖和节流

防抖 ⭐

  function debounce(fn,wait){
      var timer = null;
      return function(){
          let _this = this
          let agrs = [...arguments]
          if(timer !== null){
              clearTimeout(timer);
          }
          timer = setTimeout(function(){
              fn.apply(_this,args)
          },wait);
      }
  }

节流 ⭐⭐⭐

  • 第一次就执行

      function trol(fn,delay){
          var last = 0
          return function(){
              var now = Date.now()
              if(now - last > delay){
                  fn.apply(this,arguments)
                  last = now
              }
          }
      }
    
  • 第一次不立即执行,延时delay

      function trol(fn,delay){
          let timer = null
          return function(){
              let context = this
              let args = arguments
              if(timer === null){
                  timer = setTimeout(()=>{
                      fn.apply(context,args)
                      timer = null
                  },delay)
              }
          }
      }
    
  • 最后执行

      function trol(fn,delay){
           let startTime= Date.now()
           let timer = null
           return function(){
               let context = this
               let args = arguments
               let currTime = Date.now()
               let remaining = delay - (currTime - startTime)
               clearTimeout(timer)
               if(remaining <= 0){
                   fn.apply(context,args)
                   startTime = Date.now()
               }else{
                   timer = setTimeout(fn,remaining)
               }
           }
       }
    

2. 深拷贝 ⭐⭐

  • 自定义方法

      function deepClone(obj){
          let newTarget = Array.isArray(obj) ? [] : {}
          if(obj && typeof obj === 'object'){
              for(let key in obj){
                  if(typeof obj[key] === 'object'){
                      newTarget[key] = deepClone(obj[key])
                  }else{
                      newTarget[key] = obj[key]
                  }
              }
          }
          return newTarget
      }
    
  • JSON

      let obj = {
          a: 1,
          b: [2,3,5],
          c: function(){}
      }
      ​
      let res = JSON.parse(JSON.stringify(obj))
      console.log(res); //c会被忽略
    

3. 数组扁平化 ⭐⭐

  • 自带方法

      let arr = [1,2,[3,4,[5,6]]]
      arr.flat(Infinity)
    
  • 递归

      function flat(arr){
          return arr.reduce((pre,cur)=>{
              return pre.concat(Array.isArray(cur) ? flat(cur) : cur)
          },[])
      }
    
  • 队列

      function flat(arr){
          let res = []
          while(arr[0] !== undefined){
              let temp = arr.shift()
              if(Array.isArray(temp)){
                  arr.unshift(...temp)
              }else{
                  res.push(temp)
              }
          }
          return res
      }
    
  • 字符串处理

      function flat(arr){
         return arr.toString().split(',').map(v=>Number(v))
      }
    

4. 单例模式 ⭐⭐

  • 绑定在构造函数的静态方法上

  • 使用闭包

       //构造函数
      function SingleTon(){
         
      }
      ​
      //工具函数
      var getInstance = (function(){
         var instance
         return function(){
            if(!instance){
               instance = new SingleTon()
            }
            return instance
         }
      })();
    

5. 数组去重 ⭐⭐⭐

  • Set集合

      let res = [...new Set(arr)]
      //let res = Array.from(new Set(arr))
      console.log(res);
    
  • Map

      function fn(arr){
         let res = [],
             map = new Map()
         for(let i=0;i<arr.length;i++){
            let temp = arr[i]
            if(map.has(arr[i])){
               map.set(temp,true)
            }else{
               res.push(temp)
               map.set(temp,false)
            }
         }
         return res
      }
    
  • indexOf

      function fn(arr){
         let res = []
         arr.forEach(v=>{
            if(res.indexOf(v) === -1){
               res.push(v)
            }
         })
         return res
      }
    

6. 手写Promise的all和race ⭐⭐

  • 手写PromiseAll()
  function myPromiseAll(promiseArr){
     return new Promise((resolve,reject)=>{
        let count = 0,
            res = []
        for(let i=0;i<promiseArr.length;i++){
           Promise.resolve(promiseArr[i]).then(data=>{
              res[i] = data
              count ++
              if(count === promiseArr.length){
                 resolve(res)
              }
           }).catch(err=>{
              reject(err)
           })
        }
     })
  }
  • 手写 Promise.race
  function myPromiseRace(promiseArr){
     return new Promise((resolve,reject)=>{
        promiseArr.forEach(v=>{
           Promise.resolve(v).then(data=>{
              resolve(data)
           }).catch(err=>{
              reject(err)
           })
        })
     })
  }

7. 模式实现 New ⭐

  • 新建一个空对象obj
  • 把这个空对象的原型执行构造函数的原型
  • 改变this的指向执行构造函数
  • 如果构造函数的结果返回的是一个对象则返回该对象,否则返回obj
  function _new(Fn,...args){
      let obj = {}
      obj.__proto__ = Fn.prototype
      let res = Fn.apply(obj,args)
      return res instanceof Object ? res : obj
  }

8. 实现call/apply/bind ⭐⭐⭐

  • 实现call

      Function.prototype.myCall = function(context,...args){
          let _this = this // XXXX.myCall => XXX
          context = context ? Object(context) : Window
          context.fn = _this
          let r = context.fn(...args)
          delete context.fn
          return r
      }
      ​
    
  • 实现 apply

        Function.prototype.myApply = function(context,args){
                let _this = this 
                context = context ? Object(context) : Window
                context.fn = _this
                if(!args){
                  context.fn()
                }else{
                  context.fn(args)
                }
                delete context.fn
            }
    
  • 实现 bind

    • js bind的多次绑定只有第一次是有效的
    • 在Javascript中,多次 bind() 是无效的。更深层次的原因, bind() 的实现,相当于使用函数在内部包了一个 call / apply ,第二次 bind() 相当于再包住第一次 bind() ,故第二次以后的 bind 是无法生效的。
      FUnction.prototype.myBind = function(context){
         let args = [...arguments].slice(1)
         let _this = this
         fBound = function(){
             return _this.apply(this instanceof fBound ? this : context,args.concat([...arguments]))
         }
         fBound.prototype = this.prototype
          return fBound
      }
    

9. 模式Object.create()实现 ⭐

Object.create()会将参数对象作为一个新创建的空对象的原型, 并返回这个空对象

  function _create(proto){
     function F(){}
     F.prototype = proto
     return new F()
  }

10. 千分位分隔符 ⭐

function thousandBitSeparator(num) {
    return num && num
        .toString()
        .replace(/(\d)(?=(\d{3})+\.)/g, function($0, $1) {
            return $1 + ",";
        });
}
console.log(thousandBitSeparator(-1234567.9012));

11. 实现三角形 ⭐⭐

  • 利用边框均分的原理

      <style>
          * {
              margin: 0;
              padding: 0;
          }
          div {
              width: 0;
              height: 0;
              border-left: 40px solid transparent;
              border-right: 40px solid transparent;
              border-top: 40px solid blue;
              border-bottom: 40px solid transparent;
          }
      </style><body>
          <div></div>
      </body>
    

13. 打乱数组 ⭐⭐

  • sort

    数组的sort方法是按照return的值的正负去做排序判定,思路就是使得返回的值随机正负

       function fn(arr){
           return arr.sort(()=> 0.5 - Math.random())
       }
      ​
      let res = fn([1,3,5,7,9])
      console.log(res);
    
  • 洗牌算法

    • 找到数组最后一个元素
    • 从数组开头到最后一个元素之间,找到随机的一个数
    • 交换两个位置
    • 此时最后一个是已经是乱序后的结果
    • 执行最后一个元素的索引前移
    • 指导指向的索引为0
      function randomSortArry(arr){
              let len = arr.length
              for(let i = len-1;i>=0;i--){
                  var randomIndex = Math.floor(Math.random()*(i+1))
                  var temp = arr[i]
                  arr[i] = arr[randomIndex]
                  arr[randomIndex] = temp
              }
              return arr
      }
    

14. 驼峰,下划线相互转换 ⭐⭐⭐

  • 驼峰转下划线

      //驼峰转下划线
      function fn(str){
          return str.replace(/([A-Z])/g,'_$1').toLowerCase()
      }
    
  • 下划线转驼峰

      function fn2(str){
          return str.replace(/_(\w)/g,function(all,letter){
              return letter.toUpperCase()
          })
      }
    

15. 去掉空格

写一个function,清除字符串前后的空格。(兼容所有浏览器)

  function Trim(str)
   { 
    return str.replace(/(^\s*)|(\s*$)/g, ""); 
  }