Skip to content

定义

是能被实例化一次的类或者对象(只能存在一个)

特点

  • 只允许实例化一次的对象类
  • 对于十分复杂的对象类,往往可以节省资源占用
  • 通常也被用来管理命名空间

作用

管理命名空间,管理数据,方法存储

应用

  • 一些代码库中命名空间就是通过单例面试实现的
  • 管理数据的存储,例如模拟静态变量

coding

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>单例模式</title>
  </head>

  <body>
    <div class="eg2"></div>
    <script>
      const Person = (() => {
        class Person {
          constructor(name, age, gender) {
            this.name = name
            this.age = age
            this.gender = gender
          }
          sayHi() {
            console.log('hello world!')
          }
        }

        let instance = null
        return function singleTon(...arg) {
          if (!instance) instance = new Person(...arg)
          return instance
        }
      })()

      const p1 = new Person('wcd', 25, 'boy')
      const p2 = new Person('ll', 25, 'girl')

      console.log(p1, p2)
      console.log(p1 === p2)
    </script>
  </body>
</html>

举例-单例模式_自定义弹出层

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>单例模式_自定义弹出层</title>
    <style>
      div.tip {
        width: 500px;
        height: fit-content;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: auto;
        background-color: #fff;
        background-clip: padding-box;
        border-radius: 4px;
        box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
        pointer-events: auto;

        display: none;
      }

      div.tip > .top {
        background-color: skyblue;
        padding: 16px 24px;
        color: rgba(0, 0, 0, 0.65);
        border-bottom: 1px solid #e8e8e8;
        border-radius: 4px 4px 0 0;
        line-height: 22px;
      }

      div.tip > .top > span {
        float: right;
        width: 20px;
        height: 20px;
        border-radius: 50%;
        cursor: pointer;
        background-color: #fff;
        font-size: 16px;
        text-align: center;
        line-height: 20px;
      }

      .tip > .content {
        padding: 24px;
        font-size: 14px;
        line-height: 1.5;
        word-wrap: break-word;
      }

      .tip > .btns {
        display: flex;
        justify-content: flex-end;
        padding: 10px 16px;
        background: transparent;
        border-top: 1px solid #e8e8e8;
        border-radius: 0 0 4px 4px;
      }
    </style>
  </head>

  <body>
    <div class="tip">
      <div class="top">
        标题
        <span>X</span>
      </div>
      <div class="content">
        <p>提示内容</p>
      </div>
      <div class="btns">
        <button>取消</button>
        <button>确定</button>
      </div>
    </div>

    <script>
      const Tip = (() => {
        class Tip {
          constructor() {
            this.ele = document.createElement('div')
            this.ele.className = 'tip'
            document.body.appendChild(this.ele)
            this.callback = () => {}
            this.bindEvent()
          }

          setContent(txt) {
            this.ele.innerHTML = `
            <div class="top">标题
              <span class="close">X</span>
            </div>
            <div class="content">
              <p>${txt}</p>
            </div>
            <div class="btns">
              <button class="cancel">取消</button>
              <button class="ok">确定</button>
            </div>
          `

            this.ele.style.display = 'block'
          }
          bindEvent() {
            this.ele.addEventListener('click', (e = window.event) => {
              const target = e.target || e.srcElement

              const { className } = target

              switch (className) {
                case 'close':
                  this.ele.style.display = 'none'
                  break
                case 'cancel':
                  this.ele.style.display = 'none'
                  this.callback(false)
                  break
                case 'ok':
                  this.ele.style.display = 'none'
                  this.callback(true)
                  break
              }
            })
          }
          setStyle(val) {
            this.ele.querySelector('.top').style.backgroundColor = val
          }
        }

        let instance = null
        return function singleTon(options = {}, cb = function () {}) {
          const { txt = 'Hello World', topBG = 'skyblue' } = options

          if (!instance) instance = new Tip()

          instance.setContent(txt)
          instance.setStyle(topBG)
          instance.callback = cb

          return instance
        }
      })()

      Tip(
        {
          txt: 'Hello World',
          topBG: '#1890ff',
        },
        (res) => {
          console.log('print: ', res)
        }
      )
    </script>
  </body>
</html>