• 前端js手写面试题汇总(二)


    1. 实现防抖函数(debounce)

      防抖函数原理:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

      那么与节流函数的区别直接看这个动画实现即可。

      手写简化版:

      = null;   return (...args) => {
           
          clearTimeout(timer);
          timer = setTimeout(() => {
           
            fn.apply(this, args);
          }, delay);   }; };
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      适用场景:

      • 按钮提交场景:防止多次提交按钮,只执行最后提交的一次
      • 服务端验证场景:表单验证需要服务端配合,只执行一段连续的输入事件的最后一次,还有搜索联想词功能类似

      生存环境请用lodash.debounce

      模板引擎实现

      data = {
              name: '姓名',   age: 18 } render(template, data); //
      我是姓名,年龄18,性别undefined
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      /\{\{(\w+)\}\}/; // 模板字符串正则   if (reg.test(template)) { //
      判断模板里是否有模板字符串
          const name = reg.exec(template)[1]; // 查找当前模板里第一个模板字符串的字段
          template = template.replace(reg, data[name]); // 将第一个模板字符串渲染
          return render(template, data); // 递归的渲染并返回渲染后的结构   }   return template; // 如果模板没有模板字符串直接返回 }
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      实现日期格式化函数

      输入:

      2020/12/01 dateFormat(new Date('2020-04-01'), 'yyyy/MM/dd') //
      2020/04/01 dateFormat(new Date('2020-04-01'), 'yyyy年MM月dd日') //
      20200401
      • 1
      • 2
      • 3
      • 4
          var day = dateInput.getDate() 
          var month = dateInput.getMonth() + 1  
          var year = dateInput.getFullYear()   
          format = format.replace(/yyyy/, year)
          format = format.replace(/MM/,month)
          format = format.replace(/dd/,day)
          return format }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      实现bind方法

      bind 的实现对比其他两个函数略微地复杂了一点,涉及到参数合并(类似函数柯里化),因为 bind 需要返回一个函数,需要判断一些边界问题,以下是 bind 的实现

      • bind 返回了一个函数,对于函数来说有两种方式调用,一种是直接调用,一种是通过 new 的方式,我们先来说直接调用的方式
      • 对于直接调用来说,这里选择了 apply 的方式实现,但是对于参数需要注意以下情况:因为 bind 可以实现类似这样的代码 f.bind(obj, 1)(2),所以我们需要将两边的参数拼接起来
      • 最后来说通过 new 的方式,对于 new 的情况来说,不会被任何方式改变 this,所以对于这种情况我们需要忽略传入的 this

      简洁版本

      • 对于普通函数,绑定this指向
      • 对于构造函数,要保证原函数的原型对象上的属性不能丢失
      ...args) {
              // this表示调用bind的函数   let self = this;
      
        //返回了一个函数,...innerArgs为实际调用时传入的参数   let fBound =
      function(...innerArgs) {
            
            //this instanceof fBound为true表示构造函数的情况。如new func.bind(obj)
            // 当作为构造函数时,this 指向实例,此时 this instanceof fBound 结果为 true,可以让实例获得来自绑定函数的值
            // 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 context
            return self.apply(
              this instanceof fBound ? this : context, 
              args.concat(innerArgs)
            );   }
      
        // 如果绑定的是构造函数,那么需要继承构造函数原型属性和方法:保证原函数的原型对象上的属性不丢失   // 实现继承的方式:
      使用Object.create   fBound.prototype = Object.create(this.prototype); 
      return fBound; } ```
      
      ```javascript // 测试用例
      
      function Person(name, age) {
              console.log('Person name:', name);  
      console.log('Person age:', age);   console.log('Person this:',
      this); // 构造函数this指向实例对象 }
      
      // 构造函数原型的方法 Person.prototype.say = function() {  
      console.log('person say'); }
      
      // 普通函数 function normalFun(name, age) {   console.log('普通函数 name:',
      name);    console.log('普通函数 age:', age);    console.log('普通函数
      this:', this);  // 普通函数this指向绑定bind的第一个参数 也就是例子中的obj }
      
      
      var obj = {
              name: 'poetries',   age: 18 }
      
      // 先测试作为构造函数调用 var bindFun = Person.myBind(obj, 'poetry1') //
      undefined var a = new bindFun(10) // Person name: poetry1、Person
      age: 10、Person this: fBound {
           } a.say() // person say
      
      // 再测试作为普通函数调用 var bindNormalFun = normalFun.myBind(obj, 'poetry2')
      // undefined bindNormalFun(12) // 普通函数name: poetry2 普通函数 age: 12
      普通函数 this: {
           name: 'poetries', age: 18} ```
      
      > 注意: `bind`之后不能再次修改`this`的指向,`bind`多次后执行,函数`this`还是指向第一次`bind`的对象
      
      
      参考:[前端手写面试题详细解答](https://kc7474.com/archives/1333?url=handwritten)
      
      
      ### 模拟Object.create
      
      Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
      
      ```javascript // 模拟 Object.create
      
      function create(proto) {
              function F() {
           }   F.prototype = proto
      • 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
  • 相关阅读:
    新电脑重装系统好吗?电脑重装系统的好坏
    自学Python只看这个够不够........?
    ValueError: (‘Unrecognized keyword arguments:‘, dict_keys([‘ragged‘]))的问题 报错解决
    视频剪辑中花式抠图的代码实操与案例详述
    FreeRTOS学习 -- 任务
    从虚拟化走向云原生,红帽OpenShift“一手托两家”
    男孩姓卜取什么名字好听
    问题记录1 json解析问题
    【语音识别入门】My-Voice-Analysis
    Python之魔幻切片——万物可切(只要是序列对象)。负整数步长一出,序列瞬间倒置,可以玩儿更多花样。
  • 原文地址:https://blog.csdn.net/helloworld1024fd/article/details/127877483