本文详解 JavaScript 中单例模式的应用,通过静态方法与闭包两种方案控制实例创建,解决模态框重复生成问题。对比传统面向对象方式,展示如何利用闭包特性确保全局仅存在一个模态框实例,提升页面性能与用户体验。
单例模式核心概念
单例模式的核心概念是什么?
“单”代表唯一,“例”指代实例化后的对象。该模式旨在确保一个构造函数仅能生成一个实例。理解并掌握单例模式具有重要意义,其应用场景广泛,例如网站中频繁点击弹出的模态框,无论用户操作多少次,系统应只创建并显示一个实例;又如后台数据库连接池,通常也维持单一连接以优化资源。本文聚焦于单例模式在模态框中的具体应用,首要任务是厘清如何实现单例逻辑。
常规构造函数方式分析
首先回顾常规的构造函数结合原型链的实现方式,这是 JavaScript 中常见的对象创建范式。
function Singleton ( uName ){
this.userName = uName;
this.ins = null;
}
Singleton.prototype.showUserName = function(){
return this.userName;
}
var obj1 = new Singleton( 'ghostwu' );
var obj2 = new Singleton( 'ghostwu2' );
console.log( obj1 === obj2 ); //false
在常规模式下,每次执行 new 操作都会在内存中开辟新的空间以存储新实例,这导致无法保证全局唯一性。因此,若要实现单例,必须对 new 创建实例的过程进行严格控制。关键在于限制用户直接调用构造函数,转而采用其他机制来管理实例的生成。
静态方法实现单例
第一种实现策略:在构造函数内部定义静态方法,以此掌控实例的创建流程。
function Singleton ( uName ){
this.userName = uName;
}
Singleton.prototype.showUserName = function(){
return this.userName;
}
Singleton.getInstance = function( uName ){
if ( !this.ins ) {
this.ins = new Singleton( uName );
}
return this.ins;
}
var obj1 = Singleton.getInstance( 'ghostwu' );
var obj2 = Singleton.getInstance( 'ghostwu2' );
console.log( obj1 === obj2 ); //true
如代码第 8 行所示,逻辑判断变量 ins 是否已保存实例。若未保存,则执行 new 操作创建新实例;若已存在,则直接返回现有实例。当第二次调用时,因 ins 已存在,直接返回该对象而无需再次 new,从而确保全局仅有一个实例。
闭包与立即执行函数实现
第二种实现策略:借助闭包与立即执行函数表达式(IIFE)的特性来实现。
function Singleton ( uName ){
this.userName = uName;
}
Singleton.prototype.showUserName = function(){
return this.userName;
}
Singleton.getInstance = (function(){
var ins = null;
return function( uName ) {
if ( !ins ) {
ins = new Singleton( uName );
}
return this;
}
})();
var obj1 = Singleton.getInstance( 'ghostwu' );
var obj2 = Singleton.getInstance( 'ghostwu2' );
console.log( obj1 === obj2 );
上述两种方案均能有效实现单例。接下来,本文将选用第二种方法(闭包方案)来构建一个唯一的模态框。
传统模态框实现缺陷
三、传统面向对象方式:每次点击均生成新的模态框
相关样式定义如下:
div {
width: 200px;
height: 200px;
border:1px solid #09f;
box-shadow: 2px 2px 1px #666;
position: absolute;
}
HTML 结构部分:
<input type="button" value="弹窗">
JavaScript 逻辑部分:
var oBtn = document.querySelector("input"),
offset = 20, index = 1;
function Module( pos ){
this.offset = pos || 20;
}
Module.prototype.create = function(){
var oDiv = document.createElement( "div" );
oDiv.style.left = ( ++index ) * offset + 'px';
oDiv.style.top = ( ++index ) * offset + 'px';
oDiv.innerHTML = 'ghostwu教你用设计模式实战';
return oDiv;
}
oBtn.onclick = function(){
var oDiv = new Module();
document.body.appendChild( oDiv.create() );
}

单例模式改造模态框
四、使用单例模式进行改造
改造后的 HTML 结构:
<input type="button" value="弹窗1">
<input type="button" value="弹窗2">
var aBtn = document.querySelectorAll("input"),
offset = 20, index = 1;
function Module( pos ){
this.offset = pos || 20;
}
Module.prototype.create = function(){
var oDiv = document.createElement( "div" );
oDiv.style.left = ( ++index ) * offset + 'px';
oDiv.style.top = ( ++index ) * offset + 'px';
oDiv.innerHTML = 'ghostwu教你用设计模式实战';
return oDiv;
}
Module.one = (function(){
var ins = null, isExist = false;
return function( pos ){
if ( !ins ) ins = new Module( pos );
if ( !isExist ) {
document.body.appendChild( ins.create() );
isExist = true;
}
}
})();
aBtn[0].onclick = function(){
Module.one( 10 );
}
aBtn[1].onclick = function(){
Module.one( 10 );
}
在 Module.one 方法中,通过变量 isExist 的两种状态结合闭包特性,严格控制 DOM 元素只能被添加至页面一次。
以上即为关于使用 JavaScript 单例模式实现模态框的完整示例,希望能为读者提供有价值的参考,并欢迎大家继续支持本站内容。