Javascript Patterns--读书笔记7 (singleton)

singleton是指对于一个特定的类,只会产生一个实例。这就是说,当你第二次用这个class去创建一个新对象时,你会得到第一次创建的那个对象。在JS中,要如何实现呢?在JS中没有类,当我们创建一个新的对象时,这个对象实际上就是singleton.当我们用直接量来创建一个对象时,这实际上就是一个新的singleton实例:
var obj= {
myprop: 'my value'
}

Using new
JS中没有类,所以照字面意思来套用singleto是没有什么意义的。但是在JS中可以用new通过constructor来创建对象,而当你用new来创建一系列对象的时候,如果想得到返回的是同一个对象的指针,singleton就派上用场了。
我们可以利用下面三种方式来创建一个singleton:

  •  我们可以用一个全局变量来存储这个实例,当然,这并不是一种值得推荐的方式 ,因为用全局变量是一个非常槽的主意。
  •  可以用一个静态属性来保存这个实例,不过有一个小缺陷,就是这个属性是全局可以访问的。
  •  你可以用闭包来保存这个实例,这个可以保证这是一个私有的变量,外部的代码并不能修改它。

Instance in a static property

View Code
function Universe() {
if(typeof Universe.instance === 'object') {
return Univese.instance;
}
//添加一些属性
this.start_time = 0;

Universe.insance = this;

}

//testing
var uni = new Universe();
var uni2 = new Universe();
uni === uni2; //true

Instance in a clousre
function Universe() {
var instance = this;

this.start_time = 0;

Universe = function() {
return instance;
}
}
//testing
var uni = new Universe();
var uni2 = new Universe();

uni === uni2;//true

让我们来看一下上面的代码存在着什么问题,

View Code
Universe.protoype.nothing = true;
var uni = new Universe();
Univere.protoype.everything = true;
var uni2 = new Universe();

//Testing;
uni.nothing;//true
uni2.nothing;//true;
uni.everything;//undefined
uni2.everything;//undefined

uni.constructor.name;//"Universe"
uni.connstructor === Universe;//false

上面的代码为什么表现的如此怪异呢,这是因为uni.constructor指向的那个是原先的那个Universe()而不是重新定义的那个Universe()

让我们来看一个新的改良过的:

View Code
function Universe() {
//the cached instance
var instance;

//重新覆写constructor
Universe = function Universe() {
return instance;
}
//重新覆写prototype properties
Universe.prototype = this;
//the instance
instnace = new Universe();
instance.constructor = Universe;

instance.start_time = 0;
instance.bang = "big";

return instance
}

 

如果我们再用上面的测试用例重新测一下,就会发现这是正确的了。

我们再看一种新实现方式,把constrcutor和instance都包在一个immediate function中,当第一次调用构造函数的时候,它创造一个对象,instance会指向它。从第二次调用,constructor仅会简单的返回这个么有变量(instance)

View Code
var Universe;
(function(){
    var instance;
    Universe = function Universe() {
    if(instance) {
        return instance;
    }
    instance = this;
    //all the functionality
    this.start_time = 0;
    this.bang = "Big";
    };
}());    
posted @ 2012-09-29 17:16  moonreplace  阅读(242)  评论(0编辑  收藏  举报