js单例模式

js实现单例模式,经常使用两种方法,一种是使用构造函数的静态属性中缓存该实例,另一种是将实例包装在闭包中。

第一种实现方式:

//静态属性中单例模式
function Universe() {
    if (typeof Universe.instance === "object") {
        return Universe.instance;
    }
    //正常运行
    this.start_time = 0;
    this.bang = "Big";

    //缓存
    Universe.instance = this;
    //隐式返回
    //return this;
}

var uni = new Universe();
var uni2 = new Universe();
console.log(uni === uni2 );  //true

第二种实现方式:

/闭包中实现单例模式
function Universe(){
    //缓存实例
    var instance = this;
    //正常进行
    this.start_time = 0;
    this.bang = "Big";
    //重写该构造函数
    Universe = function(){
        return instance;
    }
    //隐式返回
    //return this;
}
var uni = new Universe();
var uni2 = new Universe();
console.log(uni == uni2);  //true

上面实现单例模式有个缺点,就是重写构造函数,会丢失所有在初始化和重定义时刻之间添加到它里面的属性,如下

//test
Universe.prototype.nothing = true;
var uni = new Universe();
//在创建初始化对象之后,再次向该原型添加属性 Universe.prototype.something = true; var uni2 = new Universe(); console.log(uni.nothing); //true console.log(uni2.nothing); //true console.log(uni2.something); //undefined console.log(uni2.something); //undefined console.log(uni.constructor.name); //Universe console.log(uni.constructor === Universe); //false

其中uni.constructor仍然指向了原始的构造函数。

如果需要使原型和构造函数指针按照预期的那样运行,可以向下面一样改写代码

//如果需要使原型和构造函数指针能够按照预期那样运行,改写如下
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;
}
//test
Universe.prototype.nothing = true;
var uni = new Universe();
//在创建初始化对象之后,再次向该原型添加属性
Universe.prototype.something = true;
var uni2 = new Universe();

console.log(uni.nothing);      //true
console.log(uni2.nothing);     //true
console.log(uni2.something);   //true
console.log(uni2.something);   //true
console.log(uni.constructor.name);         //Universe
console.log(uni.constructor === Universe); //true

另一种解决方案是将构造函数和实例包装在即使函数中。

var Universe;
(function(){
    var instance;
    Universe = function Universe(){
        if(instance){
            return instance;
        }
        instance = this;

        //所有的功能
        this.start_time = 0;
        this.bang = "BIg";
    }
}());
原文地址:https://www.cnblogs.com/scnuwangjie/p/5004988.html