本系列为《JavaScript设想形式与开辟实践》(作者:曾探)进修总结,如想深切相识,请支撑作者原版
单例形式
完成单例形式
单例形式的定义
是:保证一个类唯一一个实例,并供应一个接见它的全局接见点
。
单例形式是一种常常运用的形式,有一些对象我们每每只须要一个,比方登录窗口,这个窗口是唯一的,不管我们点击多少次登录按钮,这个窗口只会被建立一次,那末这个窗口就适合用单例形式来建立。
要完成一个规范的单例形式并不庞杂,无非是用一个变量
来标志当前是不是已为某个类建立过对象,假如是,则在下一次猎取该类的实例时,直接返回之前建立的对象。代码以下:
var Singleton=function(name){
this.name=name;
this.instance=null;
};
Singleton.prototype.getName=function(){
alert(this.name);
};
Singleton.getInstance=function(){
if(!this.instance){
this.instance=new Singleton(name);
}
return this.instance;
};
var a=Singleton.getInstance('sven1');
var b=Singleton.getInstance('sven2');
alert(a===b);//true
或许
var Singleton=function(name){
this.name=name;
};
Singleton.prototype.getName=function(){
alert(this.name);
};
Singleton.getInstance=(function(){
var instance=null;
return function(name){
if(!instance){
instance=new Singleton(name);
}
return instance;
}
})();
我们经由过程Singleton.getInstance来猎取Singleton类的唯一对象,这类体式格局相对简朴,然则不通明
。跟以往经由过程new XXX的体式格局猎取对象差别,这里偏要运用Singleton.getInstance来猎取对象,所以这段代码的意义并不大。
通明的单例形式
我们如今的目的是完成一个通明
的单例类。
var CreateDiv = (function() {
var instance;
var CreateDiv = function(html) {
if (instance) {
return instance;
}
this.html = html;
this.init();
return instance = this;
};
CreateDiv.prototype.init = function() {
var div = document.createElement('div');
div.innerHtml = this.html;
document.body.appendChild(div);
};
return CreateDiv;
})()
var a = new CreateDiv('sven1');
var b = new CreateDiv('sven2');
alert(a===b);//true
虽然如今完成了一个通明的单例类的编写,但它一样有一些瑕玷。为了把instance封装起来,我们运用了自实行的匿名函数和闭包,而且让这个匿名函数返回真正的Singleton组织要领,这增加了一些顺序的庞杂度,浏览起来也不是很惬意。
假定我们某天须要让这个单例类变成一个一般的类,即能够发生多个实例,那我们必需改写CreateDiv组织函数,这类修正会带来许多不必要的贫苦。
用代办完成单例形式
我们起首建立一个一般的CreateDiv类:
var CreateDiv = function(html) {
this.html = html;
this.init();
};
CreateDiv.prototype.init = function() {
var div = document.createElement('div');
div.innerHtml = this.html;
document.body.appendChild(div);
};
接下来引入代办类ProxySingletonCreate:
var ProxySingletonCreate = (function() {
var instance;
return function(html) {
if (!instance) {
instance = new CreateDiv(html);
}
return instance;
}
})();
var a = new ProxySingletonCreate('sven1');
var b = new ProxySingletonCreate('sven2');
console.log(a === b);
这样一来,CreateDiv
和ProxySingletonCreate
组合起来,完成了单例形式的结果。
JavaScript中的单例形式
前面提到的几种单例形式的完成,更多的是靠近传统面向对象言语
中的完成,单例对象从类
中建立而来。但JavaScript
现实上是一门无类
的言语,所以生搬单例形式的观点并没有意义。
单例形式的中心
是:确保只要一个实例,并供应全局接见
。全局变量
不是单例形式,但在现实运用中,我们常常会把全局变量当成单例来运用。
比方:
var a = {};
全局变量能够满足上述的两个前提,但却存在许多问题:它很轻易形成定名空间污染
。作为一般的开辟者,我们有必要削减全局变量的运用,一下几种体式格局能够相对下降
全局变量带来的定名污染。
运用定名空间
最简朴的要领依然是运用对象字面量
体式格局:
var namespace1={
a:function(){
},
b:function(){
}
};
我们还能够动态的建立定名空间:
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');
console.log(myApp);
运用闭包封装私有变量
var user=(function(){
var _name='sven',_age=29;
return {
getUserInfo:function(){
return _name+'_'+_age;
}
}
})();
惰性单例
惰性单例
指的是在须要的时刻才建立对象实例。惰性单例
是单例形式的重点,这类手艺在现实开辟中异常有效
。
我们先抽掏出一个治理单例的逻辑对象:
var getSingle=function(fn){
var result;
return function(){
return result||(result=fn.apply(this.arguments));
}
};
建立对象的要领fn被当作参数传入getSingle。
var getSingle = function(fn) {
var result;
return function() {
return result || (result = fn.apply(this.arguments));
};
};
var createLoginLayer = function() {
var div = document.createElement('div');
div.innerHTML = '我是登录窗';
div.style.width = '100px';
div.style.height = '100px';
div.style.background = 'red';
document.body.appendChild(div);
return div;
};
aa = getSingle(createLoginLayer);
aa();
result
变量由于身在闭包
中,永久不会被烧毁。在未来的要求中,假如result已被赋值,那末他将返回这个值。
以下是演示地点: