盘点js当中的手写 一 设计模式之 发布订阅和单例模式

手写题汇总 js当中有什么手写题呢?

哈喽哈喽,我是你们的金樽清酒。最近面字节和百度都失败了。并不是说八股背的不够多,而是基础不够扎实。字节让我明白算法基础不够,百度面试更让我打开了新世界的大门。百度没有问我八股,而是问我项目协作,和专业基础。所以,背八股想进大厂是不可能的,更重要的是会解决问题,代码的基础足够的牢固。那今天让我们js基础,一些常见的手写题梳理一下吧。

一.发布订阅

发布订阅这种设计模式是特别常见的。让我们简单的手写一下里面的四种方法。on,off,once,emit。
这四种方法分别有什么功能呢?
on:订阅,把事件和方法存起来
off:把事件里面的方法删除
once:一个事件只存一个方法
emit:将事件里面的方法全部都触发掉。

  • 先写on方法吧
class EventEmiter {
    constructor() {
        this.handels = {}//用一个对象来存订阅的事件
    }
    on(eventName, cb) {//在构造函数的原型上面,让实例对象隐式继承
        if (!this.handels[eventName]) {
            this.handels[eventName] = []
        }
        this.handels[eventName].push(cb)
    }//这个就是on方法,收集订阅的内容,将所有的依赖进行收集。
  }

先在构造函数上面放一个对象来存订阅的事件。
然后on方法接受两个参数,一个事件名,一个方法回调。如果这个事件不存在,给这个事件赋为空数组,再把后面的回调存进去。这就是on方法了。

盘点js当中的手写  一  设计模式之 发布订阅和单例模式
可以看到handles对象上就出现了sell事件。

  • on方法
class EventEmiter {
    constructor() {
        this.handels = {}//用一个对象来存订阅的事件
    }
    on(eventName, cb) {//在构造函数的原型上面,让实例对象隐式继承
        if (!this.handels[eventName]) {
            this.handels[eventName] = []
        }
        this.handels[eventName].push(cb)
    }//这个就是on方法,收集订阅的内容,将所有的依赖进行收集。
  }
  

   off(eventName, cb) {//取消订阅
        if (this.handels[eventName]) {
            const handels = this.handels[eventName]
            const index = handels.indexOf(cb)
            if (index !== -1) {
                handels.splice(index, 1)
            }
        }
    }

off方法也需要两个参数,它会找到该事件对应的某个方法,所以我们获取那个方法的下标,然后用splice修改。一定得事件这个数组是否存在,不然会报错,不是数组用不了数组上的方法。

盘点js当中的手写  一  设计模式之 发布订阅和单例模式

可以看到,我们on订阅了一个方法,off取消了订阅,该事件数组为空。

  • once方法
    once方法是一个事件只能订阅一次,那这个也很好写,那就判断数组是否为空,为空调用on方法,否则直接返回。
class EventEmiter {
    constructor() {
        this.handels = {}//用一个对象来存订阅的事件
    }
    on(eventName, cb) {//在构造函数的原型上面,让实例对象隐式继承
        if (!this.handels[eventName]) {
            this.handels[eventName] = []
        }
        this.handels[eventName].push(cb)
    }//这个就是on方法,收集订阅的内容,将所有的依赖进行收集。
  }
  

   off(eventName, cb) {//取消订阅
        if (this.handels[eventName]) {
            const handels = this.handels[eventName]
            const index = handels.indexOf(cb)
            if (index !== -1) {
                handels.splice(index, 1)
            }
        }
    }
    
    once(eventName, cb) {
       const handels = this.handels[eventName]
       if (!handels) {
           this.on(eventName, cb)
       }
       return
   }

盘点js当中的手写  一  设计模式之 发布订阅和单例模式

可以看到,当once两个方法后,数组里面只存第一个。

  • emit,发布事件,实际上就是触发事件里面存的所有方法。
class EventEmiter {
    constructor() {
        this.handels = {}//用一个对象来存订阅的事件
    }
    on(eventName, cb) {//在构造函数的原型上面,让实例对象隐式继承
        if (!this.handels[eventName]) {
            this.handels[eventName] = []
        }
        this.handels[eventName].push(cb)
    }//这个就是on方法,收集订阅的内容,将所有的依赖进行收集。
  }
  

   off(eventName, cb) {//取消订阅
        if (this.handels[eventName]) {
            const handels = this.handels[eventName]
            const index = handels.indexOf(cb)
            if (index !== -1) {
                handels.splice(index, 1)
            }
        }
    }
    
    once(eventName, cb) {
       const handels = this.handels[eventName]
       if (!handels) {
           this.on(eventName, cb)
       }
       return
   }
       emit(eventName) {//将事件发布,触发所有的依赖
        if (this.handels[eventName]) {
            const handles = this.handels[eventName]
            handles.forEach(cb => {
                cb()
            })
        }
    }

如果事件数组存在,就遍历这个数组,全部调用里面的函数。

盘点js当中的手写  一  设计模式之 发布订阅和单例模式
这样我们的发布订阅就写完了。

单例模式

什么是单例模式呢?通俗来说就是不管new 多少遍都是得到同一个实例对象。就像vuex就是一个单例模式。它是一个全局的状态管理,那么肯定不管new多少次都是在同一个实例对象,操作同一个对象。来来来,让我们一起实现一个简单的单例模式。

  • 方法一 用构造函数的静态属性
class Person {
    constructor(name) {
        this.name = name
    }
    static getInfo(name) {
        if (!Person.instance) {
            Person.instance = new Person(this.name)
        }
        return Person.instance
    }
}

let p1 = Person.getInfo('li')

let p2 = Person.getInfo('li')
console.log(p1 === p2);//true

在构造函数的静态上面写一个方法,在构造函数上面挂一个instance属性,属性值就是new的实例对象,如果该字段存在则直接返回。这样就是靠对象上的static静态方法实现单例模式。

  • 方法二
const help = (function () {
    let instance = null
    return function () {
        if (!instance) {
            instance = new Storage()
        }
        return instance
    }
})()
let p1 = new help()
let p2 = new help()
console.log(p1 === p2);//true

用一个辅助函数,同上的方法完成单例
最后打印的结果为true,我们就成功啦。这就是实现简单的单例模式。

结语

不要太着急赶路,而是感受路上的风景,各花各有各花香。既然学编程就要好好的一步步来,把编程基础学好,而不是人云亦云。

原文链接:https://juejin.cn/post/7355208166249005066 作者:jinzunqinjiu

(0)
上一篇 2024年4月8日 下午4:47
下一篇 2024年4月8日 下午4:57

相关推荐

发表回复

登录后才能评论