单例模式可以理解成一个构造函数,无论进行多少次实例化都指向一个实例
在第一次实例化之后通过给构造函数绑定一个静态属性来指向第一次的实例化对象,当第二次再实例化的时候将这个静态属性返回出去
function Terminator(name, height, target) {
// 如果标记不为 undefined 则直接返回之前创建的实例
if( Terminator.flag ) return Terminator.flag;
// 如果是第一次
this.name = name;
this.height = height;
this.target = target;
// 用静态属性标记是否被执行
Terminator.flag = this;
}
var robot1 = new Terminator('T800', '190cm', 'Sarah Connor');
var robot2 = new Terminator('T900', '200cm', 'John');
console.log(robot1 === robot2);
console.log(robot1);
console.log(robot2);
运行结果:
true
Terminator { name: 'T800', height: '190cm', target: 'Sarah Connor' }
Terminator { name: 'T800', height: '190cm', target: 'Sarah Connor' }
可以看出尽管第二次实例化的时候传入了不同的参数,但返回的还是第一次实例化的对象
class Terminator {
constructor(name, height, target) {
this.name = name;
this.height = height;
this.target = target;
}
// 在这里可以定义一些实例能使用的方法
// xxx
// 创建实例的方法
static build(name, height, target){
// 如果此实例之前已经创建过则返回该实例
if( this.flag ) return this.flag;
// 否则创造一个新实例
this.flag = new Terminator(name, height, target);
return this.flag;
}
}
const robot1 = Terminator.build('T800', '190cm', 'Sarah Connor');
const robot2 = Terminator.build('T900', '200cm', 'John');
console.log(robot1 === robot2);
console.log(robot1);
console.log(robot2);
运行结果:
true
Terminator { name: 'T800', height: '190cm', target: 'Sarah Connor' }
Terminator { name: 'T800', height: '190cm', target: 'Sarah Connor' }
分析:
我们也可以先声明静态属性,这样代码的可读性会比上文的做法要好一些
class Terminator {
static #flag;
constructor(name, height, target) {
this.name = name;
this.height = height;
this.target = target;
}
// 在这里可以定义一些实例能使用的方法
// xxx
// 创建实例的方法
static build(name, height, target){
// 如果此实例之前已经创建过则返回该实例
if( this.#flag ) return this.#flag;
// 否则创造一个新实例
this.#flag = new Terminator(name, height, target);
return this.#flag;
}
}
const robot1 = Terminator.build('T800', '190cm', 'Sarah Connor');
const robot2 = Terminator.build('T900', '200cm', 'John');
console.log(robot1 === robot2);
console.log(robot1);
console.log(robot2);
运行结果:
true
Terminator { name: 'T800', height: '190cm', target: 'Sarah Connor' }
Terminator { name: 'T800', height: '190cm', target: 'Sarah Connor' }
这个模式最大的好处是节省资源,有时候如果一个对象可以复用那继续用这个对象就好了,没必要额外弄一个新的对象出来;
这个模式的应用场景也可以是一个弹出提示框或者一个登陆表单;
众所周知,一个 DOM节点 被添加到页面上后再此执行添加操作的时候是无效的——也就是说一个节点只能同时被添加一次,只有一个 DOM节点 被移除后才能被重新添加;
最后:
由于单例模式比较简单,就不必多费口舌了,如果有新的想法或者发现文中有任何瑕疵欢迎在评论区留言或给我私信。
如果本文对你有帮助请点个赞再走吧!