1. 定义与核心
单例模式的定义:
保证一个类仅有一个实例,并提供一个访问它的全局访问点
单例模式的核心是:
确保只有一个实例,并提供全局访问
2. JavaScript中的单例模式
全局变量不是单例模式,但在 JavaScript 开发中,我们经常会把全局变量当成单例来使用。
var a = {}
当用这种方式创建对象a 时,对象a 确实是独一无二的。如果a 变量被声明在全局作用域下,则我们可以在代码中的任何位置使用这个变量,全局变量提供给全局访问是理所当然的。这样就满足了单例模式的两个条件。
但是全局变量容易造成命名空间污染,以下几种方式可以相对降低全局变量带来的命名污染。
- 使用命名空间
var namespace1 = {
a: function () {},
b: function () {}
}
- 使用闭包封装私有变量
var user = (function(){
var __name = 'sven',
__age = 29;
return {
getUserInfo: function(){
return __name + '-' + __age;
}
}
})();
我们用下划线来约定私有变量__name 和__age,它们被封装在闭包产生的作用域中,外部是访问不到这两个变量的,这就避免了对全局的命令污染
3. 惰性单例 *
惰性单例指的是在需要的时候才创建对象实例
场景:用户点击按钮创建一个弹窗 惰性单例模式创建弹窗
var createvar createLoginLayer = (function () {
var div;
return function () {
// 通过立即执行函数产生闭包环境,判断当前是否创建div,如果已经创建直接返回之前创建的div
if (!div) {
div = document.createElement("div");
div.innerHTML = "我是登录浮窗";
div.style.display = "none";
document.body.append(div);
}
return div;
};
})();
document.querySelector("button").onclick = function () {
var loginLayer = createLoginLayer();
loginLayer.style.display = "block";
};
通用的惰性单例
创建实例对象的职责和管理单例的职责分别放置在两个方法里,这两个方法可以独立变化而互不影响,当它们连接在一起的时候,就完成了创建唯一实例对象的功能
并且管理单例的函数是通用的 可以复用在创建其他实例对象上
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.append(div);
return div;
};
var createSingleLoginLayer = getSingle(createLoginLayer);
document.querySelector("button").onclick = function () {
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = "block";
};
总结
在创建通用惰性单例函数时用到了闭包和高阶函数的概念,单例模式是一种简单但非常实用的模式,特别是惰性单例技术,再合适的时候才创建对象,并且只创建唯一的一个。更奇妙的是,创建对象和管理单例的职责被分布在两个不同的方法中,这两个方法组合起来才具有单例模式的威力。