单例模式的定义是:
- 保证一个类仅有一个实例。
- 提供一个访问它的全局访问点。
由于JavaScript是基于对象编程,没有类的概念。所以可以直接将全局变量当成的单例来使用。但是该方法会污染全局作用域,且易被覆盖。可通过以下方式解决。
- 使用命名空间
var namespace1 = {
a: function(){
alert(1);
},
b: function() {
alert(2);
}
};
可用以下方法动态创建命名空间(引自Object-Oriented JavaScript一书):
var MyApp = {};
MyApp.namespace = function(name) {
var parts = name.split('.');
var current = MyApp;
for(var i in parts) {
if(!current[parts[i]]){
current[parts[i]] = {};
}
current = current[parts[i]];
}
};
MyApp.namespace('event');
MyApp.namespace('dom.style');
//上述代码结果:
MyApp = {
event:{},
dom:{
style:{}
}
};
- 使用闭包封装私有变量
var user = (function(){
var __name = 'sven',
__age = 29;
return {
getUserInfo: function() {
return __name + '-' + __age;
}
}
})
单例模式的应用
以上两种模式需要事先加载,影响性能,可以使用惰性单例模式实现需要时加载。
使用案例:
- 创建div浮窗,如登录浮窗,在页面中唯一。
- ajax渲染列表时的事件委托绑定,事件只需绑定一次。
创建单例管理模块
var getSingle = function(fn) { //fn为无单例模式的功能构造函数
var result; // 闭包保存创建的单例
//返回具有单例模式的构造函数
//存在单例返回原单例,不存在则使用fn创建该构造函数的单例
return function() {
return result || (result = fn.apply(this,arguments));
}
}
编写功能构造函数,并使用单例管理模块创建其单例版
var createLoginLayer = function(){
var div = document.createElement('div');
div.innerHTML = '我是登录浮窗';
div.style.display = 'none';
document.body.appendChild(div);
return div;
};
var createSingleLoginLayer = getSingle(createLoginLayer);
document.getElementById('loginBtn').onclick = function(){
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = 'block';
}
网友评论