#单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点

#实现单例模式

#

class SingleDog {
  show() {
    console.log('我是一个单例对象')
  }
  static getInstance() {
    // 判断是否已经new过1个实例
    if (!SingleDog.instance) {
      // 若这个唯一的实例不存在,那么先创建它
      SingleDog.instance = new SingleDog()
    }
    // 如果这个唯一的实例已经存在,则直接返回
    return SingleDog.instance
  }
}

const s1 = SingleDog.getInstance()
const s2 = SingleDog.getInstance()

// true
s1 === s2

#闭包

function SingleDog() {}
SingleDog.getInstance = (function () {
  // 定义自由变量instance,模拟私有变量
  let instance = null
  return function () {
    // 判断自由变量是否为null
    if (!instance) {
      // 如果为null则new出唯一实例
      instance = new SingleDog()
    }
    return instance
  }
})()

#实现 Modal

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>单例模式弹框</title>
  </head>
  <style>
    #modal {
      height: 200px;
      width: 200px;
      line-height: 200px;
      position: fixed;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      border: 1px solid black;
      text-align: center;
    }
  </style>
  <body>
    <button id="open">打开弹框</button>
    <button id="close">关闭弹框</button>
  </body>
  <script>
    // 核心逻辑,这里采用了闭包思路来实现单例模式
    const Modal = (function () {
      let modal = null
      return function () {
        if (!modal) {
          modal = document.createElement('div')
          modal.innerHTML = '我是一个全局唯一的Modal'
          modal.id = 'modal'
          modal.style.display = 'none'
          document.body.appendChild(modal)
        }
        return modal
      }
    })()

    // 点击打开按钮展示模态框
    document.getElementById('open').addEventListener('click', function () {
      // 未点击则不创建modal实例,避免不必要的内存占用;此处不用 new Modal 的形式调用也可以,和 Storage 同理
      const modal = new Modal()
      modal.style.display = 'block'
    })

    // 点击关闭按钮隐藏模态框
    document.getElementById('close').addEventListener('click', function () {
      const modal = new Modal()
      if (modal) {
        modal.style.display = 'none'
      }
    })
  </script>
</html>

#小结

单一实例