Skip to content

通用的惰性单例

javascript
// 创建对象逻辑
const createLoginLayer = function () {
  const div = document.createElement( 'div' )
  div.innerHTML = '我是登录浮窗'
  div.style.display = 'none'
  document.body.appendChild( div )

  return div
}

// 管理单例逻辑
const getSingle = function (fn) {
  let instance = null

  return function () {
    return instance || (instance = fn())
  }
}

const createSingleLoginLayer = getSingle(createLoginLayer)

document.getElementById('loginBtn').onclick = function () {
  const loginLayer = createSingleLoginLayer()
  loginLayer.style.display = 'block'
}

把创建实例对象的职责和管理单例的职责分别放置在两个方法里,这两个方法可以独立变化而互不 影响,当它们连接在一起的时候,就完成了创建唯一实例对象的功能。

这种单例模式的用途远不止创建对象,比如我们通常渲染完页面中的一个列表之后,接下来要给这个 列表绑定 click 事件,如果是通过 ajax 动态往列表里追加数据,在使用事件代理的前提下, click 事件实际上只需要在第一次渲染列表的时候被绑定一次,但是我们不想去判断当前是否是第 一次渲染列表,无论绑定 bindEvent 被执行了多少次,只会在第一次执行时给 div 绑定事件。

javascript
const getSingle = function (fn) {
  let instance = null

  return function () {
    return instance || (instance = fn())
  }
}

const bindEvent = getSingle(function () {
  document.getElementById('div').addEventListener('click', () => {
    console.log('click')
  })
  
  return true
})

const render = function () {
  console.log('开始渲染列表')
  bindEvent()
}

render()
render()
render()

每次点击 div 时,只会输出一次 'click'。