JavaScript 单例模式实现方式详解与 ES6 重构
本文详细解析 JavaScript 中单例模式的多种实现方式。从对象字面量的直接定义,到利用函数作用域和 this 指向的传统构造函数实现,再到 ES6 class 语法下的静态方法与构造函数重构。文章通过具体代码示例对比各方案的语义化程度与执行逻辑,帮助开发者理解如何确保类仅有一个实例。
JavaScript 单例模式概述
JavaScript 单例模式
概要:
单例模式的核心定义是确保一个类仅能创建一个实例,且该实例由类自身负责创建。
对象字面量实现单例
利用对象字面量直接生成一个单例:
var singleton = {
prop: 1,
method: function(){
console.log(a); //1
}
}
严格来说,对象字面量本身并不完全等同于单例模式。因为直接生成对象是字面量的固有功能,而单例模式是一种需要专门构思和设计的设计模式。
传统构造函数实现单例
在类内部用 new 生成实例的单例模式:
var instance;
var foo = function(){
if(!instance){
instance = new Singleton();
}
return instance;
function Singleton(){
this.name = 'single';
this.method = function(){
console.log(this.name);
}
};
}
var a = foo();
var b = foo();
a.method(); //single
console.log(a === b); //true
单例模式的关键在于检测实例是否已存在。若未生成,则创建新实例;若已存在,则直接返回该实例,从而保证该类始终只有一个实例。
由于 JavaScript 的函数提升(hoisting)机制,函数声明会提前,因此 singleton 函数的位置相对灵活。但每次调用都重新声明函数可能显得不够优雅。
由于 new 关键字会执行函数并将 this 指向新对象,因此可以通过判断类的 this 是否已赋值给 instance 来实现单例:
var instance;
var Singleton = function(){
if(instance){
return instance;
}
instance = this;
this.name = 'single';
this.method = function(){
console.log(this.name);
}
}
var a = new Singleton();
var b = new Singleton();
a.method(); //single
console.log(a === b); //true
此例中将 instance 指向了 Singleton 类,并在外部通过 new 实例化,这与前一种方法异曲同工。但由于是通过修改 this 来检测 Singleton 类是否执行过,个人感觉这种写法在语义上不够直观。
ES6 Class 语法重构单例
上面的例子用 es6 重构的写法。
类内部 new 生成单例:
var instance;
class foo{
static Singleton(){
if(!instance){
instance = new foo();
}
return instance;
}
method(){
this.name = 'single';
console.log(this.name);
}
}
var a = foo.Singleton();
var b = foo.Singleton();
a.method(); //single
console.log(a === b); //true
修改 this 指向生成单例:
var instance;
class foo{
constructor(){
if(!instance){
this.Singleton();
}
return instance;
}
Singleton(){
instance = this;
this.name = 'single';
this.method = function(){
console.log(this.name);
}
}
}
var a = new foo();
var b = new foo();
a.method(); //single
console.log(a === b); //true
当然,除了上述两种常见方式外,还有其他方法可以实例化单例。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
D3.js 比例尺与坐标轴的配置详解
2026-11-05 16:54:46
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
