JavaScript单体模式:命名空间与私有成员实现详解
本文深入解析JavaScript单体模式,阐述其作为命名空间划分工具的重要性。通过代码示例演示如何利用闭包实现私有变量与公有方法的封装,解决全局变量污染问题。同时介绍利用分支技术封装浏览器差异的标准写法,帮助开发者构建更清晰、易维护的JavaScript代码结构。
单体模式概述与核心特点
单体模式是一种用于划分命名空间,并将相关属性与方法组织在一起的对象结构。其核心约束在于:若该对象允许实例化,则全局范围内仅能存在一个实例,确保唯一性。
在JavaScript开发中,单体模式被视为基础且极具实用价值的核心模式之一。
该模式主要具备以下特点:
第一,通过划分命名空间,有效消除全局变量可能引发的冲突或安全隐患。
第二,利用分支技术封装不同浏览器之间的实现差异,提升兼容性。
第三,使代码结构更加内聚,从而提升代码的可读性与后期维护效率。
单体模式的基础实现方式如下:
/* 最基本的单体模式 */
var her = {
name: 'Anna',
sex: 'women',
say: function(){
// 一些处理逻辑......
},
doing: function(){
// 另一些处理函数......
}
}
命名空间的划分与实现
首先,进行命名空间的划分。
var box = {
width: 0,
height: 0,
getArea: function(){
return this.width * this.width; // js中对象成的访问必须是显示的,即this是不能省略的
},
init: function(w, h){
// width = w;
// height = h;这种方式相当于定义了两个全局变量,(没加var声明的变量为全局变量)
// 并不是对对象width和height的赋值
// 下面是正确的
this.width = w;
this.height = h;
}
} //box划分了一个命名空间,命名空间里的变量只在空间里有效
在上述基础写法中,单体内的所有成员及方法均为公有(public)状态。这意味着在单体外部可以随意修改这些成员(但无法直接访问内部局部变量)。那么,这种写法是如何提供命名空间保护的呢?
请继续向下阅读具体案例:
var box = {
width:0,
height:0,//单体的变量
getArea:function(){
return width * height;// width,height其实并不是单体的变量,而是在init中定义的全局变量
}
init:function(w,h){
width = w;
height = h;
}
}// init中width,height其实并不是单体的变量
window.onload = function(){
var init = box.getArea();
alert(init);
}
若未对init函数中的width和height进行正确初始化,代码将报错。修正方式如下:
var box = {
width:0,
height:0,
getArea:function(){
return width * height;
},
init:function(w,h){
width = w;
height = h;
}
}
window.onload = function(){
width = 0;
height = 0;
//or box.init(0,0);
var init = box.getArea();
alert(init);
}
修正后代码运行正常。需要注意的是,init和getArea函数中使用的width和height并非单体自身的属性,而是被错误地定义为了全局变量。因此,在单体外部对这些全局变量进行调用或修改不会受到单体的限制。
var box = {
width: 0,
height: 0,
getArea: function(){
return width * height;//js中对象成的访问必须是显示的,即this是不能省略的
},
init:function(w,h){
width = w;
height = h;
}
}//这里的width,height其实并不是单体的对象
window.onload = function(){
width = 0;
height = 0;
var width = box.getArea();
alert(width);
}
若按上述错误方式编写,代码将会报错。这证明之前的写法并未真正建立命名空间,全局变量依然带来潜在风险。因此,最开始的正确写法才是有效的,我们来验证一下:
var box = {
width: 2,
height: 2,
getArea: function(){
return this.width * this.height;/ /js中对象成的访问必须是显示的,即this是不能省略的
},
init:function(w,h){
this.width = w;
this.height = h;
}
}
window.onload = function(){
width = 0; // 不会影响单体中的局部变量也就是命名空间
height = 0; // 不会影响单体中的局部变量也就是命名空间
var width = box.getArea();
alert(width);
}
验证结果显示,在window.onload中定义的width和height不再干扰单体内部的同名变量。这是因为单体成功为内部的width和height建立了独立的命名空间,实现了隔离。
私有成员与公有成员的访问控制
其次,关注成员的属性访问控制。
虽然JavaScript并非严格的面向对象语言,但我们可以借助闭包机制来模拟私有成员的概念。将某些变量设为公有并非最佳实践,因此需要区分访问权限。
var her = (function(){
var name = 'Anna';
var sex = 'women';
return {
getArea: function(){
return name + 'is a' + sex;
},
init:function(b){
name = b;
}
}
})();
window.onload = function(){
her.name = 'Jock'; // 无法访问
alert(ger.getArea());
her.init('Lous');
alert(her.getArea());
}
具体规则为:私有变量和私有方法仅具有只读特性(外部不可见),而公有变量和公有方法则具备可读可写特性。
关于访问方式:
对于私有成员,在单体内部直接访问即可,无需任何前缀修饰;对于公有成员,在单体作用域内部访问时需加上“this.”前缀,而在单体作用域外部访问时,需加上“单体名.”前缀。
利用分支技术封装浏览器差异
第三,利用分支技术封装浏览器间的差异。
在使用分支技术时,需注意以下关键点:
a. 必须使用闭包来实现即时绑定(IIFE)。
b. 每个分支逻辑之间需用分号隔开。
c. 最终返回的是被选中的分支对象名称。
d. 调用时需使用“单体名.分支方法名”的形式。
// 利用单体的分支技术来定义XHR(XMLHttpRequest)对象,必须要用闭包才可以实现
var XHR = (function(){
//The three branches
var standard = {
cXHR:function(){
return new XMLHttpRequest();
}
};
var activeXNew = {
cXHR:function(){
return new ActiveXObject('Msxml2.XMLHttp');
}
};
var activeXOld = {
cXHR:function(){
return new ActiveXObject('Microsoft.XMLHttp');
}
};
//To assign(分配) the branch, try each method;return whatever doesn't fail
var testObject;
try{
testObject = standard.cXHR();
return standard;// return this branch if no error was thrown
}catch(e){
try{
testObject = activeXNew.cXHR();
return activeXNew;
}catch(e){
try{
testObject = activeXOld.cXHR();
return activeXOld;
}catch(e){
throw new Error('Create the XMLHttpRequestObject failed!');
}
}
}
})();
window.onload = function(){
alert(XHR.cXHR());
}
以上即为JavaScript单体模式的全面解析,希望能为读者提供帮助。如有任何疑问,欢迎留言交流,小编将及时回复。感谢大家对本站的支持!
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
