js设计模式之单例模式,javascript如何将一个对象设计成单例
单例模式是我们开发中一个非常典型的设计模式,js单例模式要保证全局只生成唯一实例,提供一个单一的访问入口,单例的对象可以不同于静态类,我们可以延迟单例对象的初始化,通常这种情况发生在我们需要等待加载创建单例的依赖。
js单例的好处
1.在全局中只生成一个变量,减少全局变量的污染,同时也很好的解决了命名冲突。
2.只需新创建一次对象,减少对内存资源的占用。
3.减少系统加载的时间,遇到bug更容易排查。
js单例核心是确保只有一个实例,并提供全局访问
在js中并没有类的说法,所谓的单一实例,就是指创建一个唯一的对象 ,这样的对象就满足了单例的条件,例如:
var demo={};js单例在实际项目开发中通常采用使用闭包的形式,将变量封装到闭包内,只提供一个接口给外包使用。这里来实现一个功能通过单例创建div元素,例如:
var demo =(function(){
var div;
function init(){
div=document.createElement('div');
div.innerText="创建了一个div";
document.body.appendChild(div);
}
return function(){
if(!div){
init();
}
return div;
}
})();
demo();//在页面上创建了一个div元素
demo();//已经创建了这是一个最经典的惰性单例,如果实例不存在,通过一个方法创建一个实例,如果已经存在,则返回实例的引用。这里就说明了它和静态对象不同,可以被延迟生成,也就是说在我们需要的时候才创建对象实例,而非在页面加载时就创建。
但是在这里我们会发现一些问题:通过上面的方法只能实例一个div元素,如果需要创建多个就比较麻烦了。而且创建的实例和它的管理都放于一个函数demo中,这明显不能更好的扩展。所以需要把变化的封装起来,不变的隔离开,以便于我们程序的扩展性,例如:
var demo = function(fn){
var elm;
return function(){
return elm || (elm = fn.apply(this, arguments));
}
};
var initDiv=function(){
var div=document.createElement('div');
div.innerText="创建了一个div";
document.body.appendChild(div);
return div;
};
var initP=function(){
var p=document.createElement('p');
p.innerText="创建了一个p";
document.body.appendChild(p);
return p;
};
var a=demo(initDiv);
a();//创建了一个div
a();//已经存在了
var a_1=demo(initDiv);
a_1();//又创建了一个div
var b=demo(initP);
b();//又通过demo创建了p
b();//已经存在了整理其它实现js单例的方法
方法1:
function Universe() { // 判断是否存在实例 if (typeof Universe.instance === 'object') { return Universe.instance; } // 其它内容 this.start_time = 0; this.bang = "Big"; // 缓存 Universe.instance = this; // 隐式返回this } // 测试 var uni = new Universe(); var uni2 = new Universe(); console.log(uni === uni2); // true方法2:
function Universe() { // 缓存的实例 var instance = this; // 其它内容 this.start_time = 0; this.bang = "Big"; // 重写构造函数 Universe = function () { return instance; }; } // 测试 var uni = new Universe(); var uni2 = new Universe(); uni.bang = "123"; console.log(uni === uni2); // true console.log(uni2.bang); // 123方法3:
function Universe() { // 缓存实例 var instance; // 重新构造函数 Universe = function Universe() { return instance; }; // 后期处理原型属性 Universe.prototype = this; // 实例 instance = new Universe(); // 重设构造函数指针 instance.constructor = Universe; // 其它功能 instance.start_time = 0; instance.bang = "Big"; return instance; } // 测试 var uni = new Universe(); var uni2 = new Universe(); console.log(uni === uni2); // true // 添加原型属性 Universe.prototype.nothing = true; var uni = new Universe(); Universe.prototype.everything = true; var uni2 = new Universe(); console.log(uni.nothing); // true console.log(uni2.nothing); // true console.log(uni.everything); // true console.log(uni2.everything); // true console.log(uni.constructor === Universe); // true方式4:
var Universe; (function () { var instance; Universe = function Universe() { if (instance) { return instance; } instance = this; // 其它内容 this.start_time = 0; this.bang = "Big"; }; } ()); //测试代码 var a = new Universe(); var b = new Universe(); alert(a === b); // true a.bang = "123"; alert(b.bang); // 123
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!