JavaScript 单例模式详解:从基础实现到惰性加载

作者:小括号时间:2026-10-26 07:05:15浏览:333

本文深入解析 JavaScript 中的单例模式,涵盖对象直接量、闭包封装及惰性实例化三种核心实现方式。通过对比传统立即执行函数与延迟加载技术,探讨如何有效管理全局状态、划分命名空间并优化资源加载,帮助开发者掌握构建逻辑单元的最佳实践。

单例模式核心特征与 Java 实现

单例模式主要具备三个核心特征:


第一,确保该类在整个系统中仅存在一个实例对象。


第二,该类负责自行创建这个实例,即在类内部完成自身实例的初始化。


第三,该类必须提供一个全局访问点,向整个系统公开获取该实例的接口。


在 Java 语言中,单例模式的典型实现大致如下:


具体代码示例如下:

 
class Singleton {
// 私有静态属性,存储类自身的唯一实例
private static Singleton instance = new Singleton();
// 私有构造函数,防止外部直接通过 new 创建实例
private Singleton(){}
// 公共静态工厂方法,用于获取唯一实例
public static Singleton getInstance() {
return instance;
} 
} 

调用方式如下:


具体代码示例如下:

 
Singleton obj = Singleton.getInstance();

上述单例类在类被加载时,instance 字段就会被立即实例化,即使加载器是静态的。因此,对于资源消耗大或配置复杂的单例,更合理的做法是将实例化操作推迟到首次使用时,即采用惰性加载(Lazy loading)。这种策略常用于需要加载大量数据的场景。修改后的代码如下:


具体代码示例如下:

 
class LazySingleton {
// 初始值为 null,暂不创建实例
private static LazySingleton instance = null;
// 私有构造函数,防止外部直接实例化
private LazySingleton(){}
// 公共静态工厂方法,仅在需要时创建实例
public static LazySingleton getInstance() {
if( instance == null ) {
instance = new LazySingleton();
} 
return instance;
} 
} 

使用方式与前述示例相同。


JavaScript 单例模式的应用价值

单例模式是 JavaScript 中最基础且实用的设计模式之一。它提供了一种将代码组织为单一逻辑单元的手段,该单元内的所有代码通过一个统一的变量进行访问。


在 JavaScript 中,单例模式应用广泛,可用于划分命名空间以减少全局变量的污染,也可用于分支技术中处理不同浏览器的兼容性问题。


JavaScript 实现单例模式的方式多样,每种方式各有优劣。


对象直接量实现基础单例

第一种:使用对象直接量实现最基础、最简单的单例。


具体代码示例如下:

 
var Singleton = {
attr1 : 1,
attr2 : 'hello',
method1 : function(){alert(this.attr2);},
method2 : function(arg){}
} 

在此方式中,对象的所有成员均通过 Singleton 对象加点号访问。所有成员均为公开状态,没有私有成员。当执行到变量 Singleton 时,对象会立即加载(实例化),即非惰性加载。


此外,method1 使用 this 访问单例的其他成员存在潜在风险,因为 method1 的执行上下文并不总是指向 Singleton 对象。


例如,当把 method1 作为事件监听器时,this 可能指向 DOM 元素,此时访问属性可能会提示 undefined。


闭包实现私有成员单例

第二种:使用闭包实现包含私有成员的单例。


具体代码示例如下:

 
var Singleton = function(){
var attr = 1, fn = function(){};
return {
method : function(){ fn(); },
getAttr : function(){ return attr; }
}; 
}(); 

在此方式中,通过 var 定义的成员属性 attr 和方法 fn 成为私有成员,然后返回一个包含公开接口 method 和 getAttr 的对象。未来修改实现时,只需调整私有的 attr 和 fn,而接口方法 method 和 getAttr 保持不变。使用方式如下:


具体代码示例如下:

 
Singleton.method();
Singleton.getAttr();

闭包实现惰性加载单例

第三种:使用闭包实现包含私有成员且支持惰性实例化的单例。


具体代码示例如下:

 
var LazySingleton = function(){
var attr = 1, fn = function(){};
var obj = {
method : function(){ fn(); },
getAttr : function(){ return attr; }
}; 
function init(){
return obj;
} 
return {getInstace: init};
}(); 

适用场景前文已提及:对于那些必须加载大量数据的单例,直到真正需要时才进行实例化。使用方式如下:


具体代码示例如下:

 
LazySingleton.getInstance().method();
LazySingleton.getInstance().getAttr();
作者最新文章