定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
惰性单例:在需要的时候才创建实例。
let p = null
if (!p) {
p = 'xxx'
}
以创建对话框 DOM 为例
<body>
<button id="btn">Create Modalbutton>
body>
<script>
const createModal = (function() {
let Modal = null
return function() {
if (!Modal) {
Modal = document.createElement('div')
Modal.innerHTML = 'I am Modal component'
Modal.style.display = 'none'
document.body.appendChild(Modal)
}
return Modal
}
})()
const btn = document.querySelector('#btn')
const callback = () => {
const Modal = createModal()
console.log('Modal = ', Modal);
Modal.style.display = 'block'
}
btn.addEventListener('click', callback)
script>
虽然这里实现了基本功能:第一次点击按钮时生成 Modal DOM,以后每次点击只会调用 callback 函数,不再生成额外 Modal DOM。
但还是有一些问题
通过将可变与不可变的部分隔离开,我们可以换种写法
把创建对象和管理单例的职责成功区分开
<body>
<button id="btn">Clickbutton>
body>
<script>
const useSingleton = function (fn) {
// 创建指针
let p = null
return function () {
return p || (p = fn.apply(this, arguments))
}
}
const createModal = () => {
const Modal = document.createElement('div')
Modal.innerHTML = 'I am Modal Component!'
Modal.style.display = 'none'
document.body.appendChild(Modal)
return Modal
}
const createSingleModal = useSingleton(createModal)
const callback = () => {
const Modal = createSingleModal()
console.log('Modal = ', Modal)
Modal.style.display = 'block'
}
const btn = document.querySelector('#btn')
btn.addEventListener('click', callback)
script>
更多代码可在 GitHub 获取~