保证一个类仅有一个实例,并提供一个访问它的全局访问点。

如何实现

实现单例模式无非是用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象。
  1. 第一种方法
var Singleton = function (name) {
    this.name = name;
    this.instance = null;
};

Singleton.prototype.getName = function () {
    console.log(this.name);
};

Singleton.getInstance = function (name) {
    if (!this.instance) {
        this.instance = new Singleton(name);
    }

    return this.instance;
};

let test1 = Singleton.getInstance('name1');
let test2 = Singleton.getInstance('name2');

console.log(test1 == test2);
  1. 第二种方法
var Singleton = function (name) {
    this.name = name;
};

Singleton.prototype.getName = function () {
    console.log(this.name);
};

Singleton.getInstance = (function () {
    // 使用匿名函数闭包防止全局变量的污染
    let instance = null;
    return function (name) {
        if (!instance) {
            instance = new Singleton(name);
        }
        return instance;
    };
})();

let test1 = Singleton.getInstance('name1');
let test2 = Singleton.getInstance('name2');
console.log(test1 == test2);

JavaScript 中的单例模式

核心是确保只有一个实例,并提供全局访问。全局变量不是单例模式,在 js 中我们经常把全局变量当成单例使用。

避免全局变量

  1. 使用命名空间
var Myapp = {};
Myapp.namespace = function (name) {};
Myapp.namespace('event');

// 以上代码等同于如下代码
var MyApp = {
    event: {},
};
  1. 使用闭包封装私有变量
var user = (function () {
    var _name;

    return {
        getUserInfo() {
            return _name;
        },
    };
})();

惰性单例

实例对象总是在我们调用的时候才被创建,而不是在加载好的时候创建。
  • 假设我们是 博客 的开发人员网址是 http://blog.niumingxin.com/ 当点击用户名的时候出现一个浮窗,
    很明显这个浮窗在页面里总是唯一的,不可能出现同时存在两个窗口的情况。用户点击的时候才开始创建该浮窗。
// 单例模式的实现
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.display = 'none';
    document.body.appendChild(div);
    return div;
};
var createSingleLoginLayer = getSingle(createLoginLayer);
document.getElementById('loginBtn').onclick = function () {
    var loginLayer = createSingleLoginLayer();
    loginLayer.style.display = 'block';
};

// ifame测试
var createSingleIframe = getSingle(function () {
    var iframe = document.createElement('iframe');
    document.body.appendChild(iframe);
    return iframe;
});
document.getElementById('loginBtn').onclick = function () {
    var loginLayer = createSingleIframe();
    loginLayer.src = 'http://blog.niumingxin.com/';
};

微言
0 声望0 粉丝

« 上一篇
闭包
下一篇 »
策略模式