当前位置: 首页 > article >正文

js-19-手写题

目录

  • 1. 手写call函数
  • 2. 手写apply函数
  • 3. 手写bind函数
  • 4. 手写new操作符
  • 5. 手写instanceof方法
  • 6. 手写Object.create方法
  • 7. 手写防抖函数
  • 8. 手写节流函数
    • 1)时间戳实现
    • 2)定时器实现

1. 手写call函数

    Function.prototype.myCall = function (context, ...args) {
      if (typeof this !== 'function') {
        throw new Error('type error')
      }

      context = context || window
      context.fn = this

      let result = context.fn(...args)
      return result
    }

    function Person(name, age) {
      this.name = name
      this.age = age
      console.log('name=', this.name)
      console.log('age=', this.age)
      console.log('num=', this.num)
    }

    let obj = {
      num: 100
    }
    
    Person.myCall(obj, 'lisi', 18)

2. 手写apply函数

    Function.prototype.myApply = function (context, args) {
      if (typeof this !== 'function') {
        throw new Error('type error')
      }

      context = context || window
      context.fn = this
      
      let result = context.fn(...args)
      delete context.fn
      
      return result
    }

    function Person(name, age) {
      this.name = name
      this.age = age
      return `${this.name},${this.age},num=${this.num}`
    }

    let obj = {
      num: 100
    }

    console.log(Person.myApply(obj, ['lisi', 18]))

3. 手写bind函数

    Function.prototype.myBind = function (context, ...args1) {
      if (typeof this !== 'function') {
        throw new Error('error')
      }

      const _this = this

      return function (...args2) {
        return _this.apply(context, [...args1, ...args2])
      }
    }

    function test(name, age) {
      this.name = name
      this.age = age
      return this.name + ',' + this.age + ',' + this.num
    }

    let obj = {
      num: 100
    }

    let res = test.myBind(obj, 'lisi')
    console.log(res(18))

4. 手写new操作符

    function myNew(constructor, ...args) {
      let newObj = {}
      newObj.__proto__ = constructor.prototype

      let res = constructor.apply(newObj, args)
      return res instanceof Object ? res : newObj
    }

    function Person(name, age) {
      this.name = name
      this.age = age
    }

    const person = myNew(Person, 'lisi', 18)
    console.log(person)
    console.log(person.__proto__ === Person.prototype)

5. 手写instanceof方法

    // 注意:instanceof只能用来判断复杂数据类型
    function myInstanceof(left, right) {
      if(left === null || typeof left !== 'object') {
        throw new Error('type error')
      }

      let proto = left.__proto__
      let prototype = right.prototype

      while(true) {
        if(!proto) return false
        if(proto === prototype) return true
        proto = proto.__proto__
      }
    }

    let res1 = myInstanceof([1,2], Array)
    console.log(res1)

    let res2 = myInstanceof({a: 1}, Object)
    console.log(res2)

    let res3 = myInstanceof(null, Function)
    console.log(res3)

6. 手写Object.create方法

    // Object.create 
    // 创建一个对象,并且可以指定对象的原型,同时也可以在新对象上定义属性
    function myObjectCreate(context, propertiesObject = null) {
      function F() { }
      F.prototype = context
      const obj = new F()

      if (propertiesObject !== null) {
        Object.defineProperties(obj, propertiesObject)
      }

      return obj
    }

    let person = {
      name: 'zhangsan',
      fn: function () {
        console.log(this.desc)
      }
    }

    let res = myObjectCreate(person, {
      desc: {
        value: 'lisi', // desc属性值为lisi
        writable: false, // false表示属性值不可修改
        enumerable: true, // true表示属性是可枚举的
        configurable: true // true表示属性的描述符可以被修改,且属性可以从对象上删除
      }
    })
    console.log(res.name)
    res.fn()

7. 手写防抖函数

        const box = document.querySelector('.box')
        // 防抖:事件被触发n秒后执行回调,如果在这n秒内事件又被触发,则重新计时

        // 事件回调
        function desc(e, name, age) {
            console.log(e)
            console.log(name)
            console.log(age)
        }

        // 防抖函数
        function debounce(fn, wait, ...args1) {
            let timer = null

            return function (...args2) {
                const context = this

                if (timer) {
                    clearTimeout(timer)
                    timer = null
                }

                timer = setTimeout(() => {
                    fn.apply(context, [...args2, ...args1])
                }, wait)
            }
        }

        box.addEventListener('click', debounce(desc, 1000, 'lisi', 18))

8. 手写节流函数

1)时间戳实现

        // 节流:一段时间内事件被多次触发,但是最终只执行一次事件回调
        const box = document.querySelector('.box')

        // 事件回调
        function desc(e, name, age) {
            console.log('向后端发请求')
            console.log(e)
            console.log(name)
            console.log(age)
        }

        // 节流函数
        function throttle(fn, delay, ...args1) {
            let curTime = Date.now()

            return function(...args2) {
                let nowTime = Date.now()

                if(nowTime - curTime >= delay) {
                    curTime = Date.now()
                    return fn.apply(this, [...args2, ...args1])
                }
            }
        }

        box.addEventListener('click', throttle(desc, 3000, 'lisi', 18))

2)定时器实现

        // 节流:定时器实现
        const box = document.querySelector('.box')

        function desc(e, name, age) {
            console.log('向后端发送请求')
            console.log(e)
            console.log(name)
            console.log(age)
        }

        // 节流函数
        function throttle(fn, delay, ...args1) {
            let timer = null
            return function(...args2) {
                let context = this
                if(timer) return

                timer = setTimeout(() => {
                    fn.apply(context, [...args2, ...args1])
                    timer = null
                }, delay)
            }
        }

        box.addEventListener('click', throttle(desc, 2000, 'lisi', 18))

http://www.kler.cn/a/467713.html

相关文章:

  • vue3组件化开发优势劣势分析,及一个案例
  • 浅谈棋牌游戏开发流程七:反外挂与安全体系——守护游戏公平与玩家体验
  • Spring SpEL表达式由浅入深
  • redis持久化方案
  • 【操作系统不挂科】操作系统期末考试题库<2>(单选题&简答题&计算与分析题&程序分析题&应用题)
  • 『SQLite』详解运算符
  • 软件逆向之标志位
  • 【测试工具】 Postman 基本使用
  • 【Linux】调度优先级(谦让度)
  • spring、spring boot、Springmvc 的区别和关系
  • k8s集群部署 - Dashboard v2.7
  • MySQL 8 主从同步配置(Master-Slave Replication)
  • ESP32移植Openharmony外设篇(7)土壤湿度传感器YL-69
  • Python进阶-08-继承性
  • 编译 C++ 程序:分离与保留调试信息以支持 GDB 对 Core 文件的调试
  • 如何自行解锁 ATamp;T 手机
  • UE5 slate创建SDockTab标签页的过程理解
  • Megatron - LM 怎么进行模型切分的,怎么匹配服务器的
  • 量子力学复习
  • STM32学习之MPU6050芯片 及 软件I2C读写MPU6050实验
  • linux命令行连接Postgresql常用命令
  • 【高阶数据结构】哈希表封装unordered_map、unordered_set
  • 【论文阅读】Anchor-based fast spectral ensemble clustering
  • 微服务保护—Sentinel快速入门+微服务整合 示例: 黑马商城
  • 我用AI学Android Jetpack Compose之Jetpack Compose学习路径篇
  • 字符串中常用函数