目录
1.定义
单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2.全局变量与减少命名污染
全局变量不是单例模式,但在JavaScript开发中,我们经常会把全局变量当成单例来使用。例如:
var a = {};
a既是独一无二也可以全局访问,满足单例模式定义;但全局变量容易造成命名污染,大项目开发时随时有可能被别人覆盖。所以要用以下俩种方式相对降低全局变量带来的命名污染:
-
使用命名空间
var namespace1 = { a: function(){ alert (1); }, b: function(){ alert (2); } };
把a和b都定义为namespace1的属性,这样可以减少变量和全局作用域打交道的机会。
-
使用闭包封装私有变量
var user = (function () { var __name = 'xxx', __age = 21; return { getUserInfo: function () { return __name + '-' + __age; } } })();
我们用下划线来约定私有变量__name和__age,它们被封装在闭包产生的作用域中,外部是访问不到这两个变量的,这就避免了对全局的命令污染。
3.通用的惰性单例
惰性单例指的是在需要的时候才创建对象实例。
-
将管理代理的逻辑封装成函数
function getSingle(fn) { var result; // 在闭包中不销毁 return function () { // 如果result被赋值,则返回;没有则执行创建方法 return result || (result = fn.apply(this, arguments)); } }
-
使用例子(点击按钮才生成登录弹窗并显示)
// 1.声明创建方法 var createLoginLayer = function () { var div = document.createElement('div'); div.innerHTML = '我是登录弹窗'; div.style.display = 'none'; document.body.appendChild(div); return div; } // 2.传入创建方法返回单例方法,还没创建 var createSingleLoginLayer = getSingle(createLoginLayer); // 3.在需要的时候创建 document.getElementById('loginBtn').onclick = function () { var loginLayer = createSingleLoginLayer(); loginLayer.style.display = 'block'; }
-
使用例子(列表渲染只绑定一次事件)
var bindEvent = getSingle(function () { document.getElementById('div1').onclick = function name() { alert('click'); } return true; // 返回true是为了让单例方法不执行||后的创建 }) var render = function () { console.log('开始渲染列表'); bindEvent(); } render(); render(); render(); // render函数和bindEvent函数都分别执行了3次,但div实际上只被绑定了一个事件
注:以上参考《JavaScript设计模式与开发实践》的摘录笔记,强烈建议大家阅读原书!