解决需求:在程序运行过程中,程序只有一个构造对象,可以解决内存开销,共用相同数据
应用实例:全局存储的用户对象、vuex、全局模态框
实现方式:类对象的实现,闭包实现
2.1基础实现
let instance = null;
function Single() {
if (instance) {
return instance;
}
instance = this;
}
const single1 = new Single();
const single2 = new Single();
console.log(single1 === single2);//true
2.2.使用全局变量容易被污染,这个时候使用闭包的实现,将变量封存在内部。
const createSingle = (function () {
let instance = null;
function Single() {
if (instance) {
return instance;
}
instance = this;
}
return new Single();
})();
const single1 = createSingle;
const single2 = createSingle;
console.log(single1 === single2);//true
2.3使用惰性函数实现,惰性函数执行一次,相当于执行到Single后把函数替换掉了的理解
function Single() {
let instance = this;
Single = function () {
return instance;
};
}
const single1 = new Single();
const single2 = new Single();
console.log(single1 === single2);//true
2.4 惰性函数会丢失原型对象
function Single() {
let instance = this;
let oldPrototype = Single.prototype;
Single = function () {
return instance;
};
Single.prototype = oldPrototype;
instance = new Single();
instance.constructor = Single;
return instance;
}
const single1 = new Single();
const single2 = new Single();
console.log(single1 === single2);
2.5使用es6语法糖class实现单例模式
class Singleclass Single {
static getInstance() {
if (!Single.instance) {
Single.instance = new Single();
}
return Single.instance;
}
}
const single1 = Single.getInstance();
const single2 = Single.getInstance();
console.log(single1 === single2);
3.1 全局模态框实现
<!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>
3.2 vuex简单实现
3.3 用户对象存储封装
// 定义Storage
class Storage {
static getInstance() {
// 判断是否已经new过1个实例
if (!Storage.instance) {
// 若这个唯一的实例不存在,那么先创建它
Storage.instance = new Storage()
}
// 如果这个唯一的实例已经存在,则直接返回
return Storage.instance
}
getItem (key) {
return localStorage.getItem(key)
}
setItem (key, value) {
return localStorage.setItem(key, value)
}
}
const storage1 = Storage.getInstance()
const storage2 = Storage.getInstance()
storage1.setItem('name', '李雷')
// 李雷
storage1.getItem('name')
// 也是李雷
storage2.getItem('name')
// 返回true
storage1 === storage2