单例模式

定义:保证一个对象(类)仅有一个实例,并提供一个访问它的全局访问点;

实现原理:利用闭包来保持对一个局部变量的引用,这个变量保存着首次创建的唯一的实例;

主要用于:全局缓存、登录浮窗等只需要唯一一个实例的时候;

一. 为一个非单例模式对象(如:Demo)实现单例模式的方法:

给Demo添加一个静态方法来实现单例:

Demo.getSingle = (function(){
var demo = null;
return function(name){
if(!demo){
demo = new Demo(name);
}
return demo;
}
})();

用法:

非单例模式:

var a = new Demo('Peter');

单例模式:

var b1 = Demo.getSingle('Peter');
var b2 = Demo.getSingle('Sufei');
b1 === b2;//true,都引用的是new Demo('Peter')

通过代理类来实现单例:

var ProxyDemo = (function(){
var demo = null;
return function(name){
if(!demo){
demo = new Demo(name);
}
return demo;
}
})();

用法:

非单例模式:

var a = new Demo('Peter');

单例模式:

var b = new ProxyDemo('Peter');

二. 惰性单例模式:只在需要的时候才创建该单例;

以下是通用惰性单例的创建方法:

var getSingle = function(foo){
var single = null;
return function(){
return single || (single = foo.apply(this,arguments));
}
};

用法:

var createLoginLayer = function(){
var frag = document.createDocumentFragment();
var div = document.createElement('div');
div.style.display = 'none';
//以下给div添加其它登录元素
...
document.body.appendChild(frag.appendChild(div));
return div;
}
var createSingleLoginLayer = getSingle(createLoginLayer);
//当用户第一次点击按钮(id = 'lgBtn')时,来创建并显示登录窗口,之后重复点击按钮不会重复创建;
document.getElementById('lgBtn').onclick = function(){
var lg = createSingleLoginLayer();
lg.style.display = 'block';
}

创建单例的其它方法:

方法1:

function Universe() {
// 判断是否存在实例
if (typeof Universe.instance === 'object') {
return Universe.instance;
}
// 其它内容
this.start_time = 0;
this.bang = "Big";
// 缓存
Universe.instance = this;
// 隐式返回this
}
// 测试
var uni = new Universe();
var uni2 = new Universe();
console.log(uni === uni2); // true

方法2:

function Universe() {
// 缓存的实例
var instance = this;
// 其它内容
this.start_time = 0;
this.bang = "Big";
// 重写构造函数
Universe = function () {
return instance;
};
}

附:缓存函数的计算结果,如计算一个数的数列

以下是不缓存的写法,非常慢!

function foo(n){
results = n < 2 ? n : foo(n - 1) + foo(n - 2);
return results;
}
console.log(foo(40));//得计算好几秒

以下是缓存写法,基本瞬间出结果!

var cache = {};
function foo(n){
if(!cache[n]){
cache[n] = n < 2 ? n : foo(n - 1) + foo(n - 2);
}
return cache[n];
}
console.log(foo(100));

更好的写法:

var foo = (function(){
var cache = {};
return function(n){
if(!cache[n]){
cache[n] = n < 2 ? n : foo(n - 1) + foo(n - 2);
}
return cache[n];
};
})();
console.log(foo(100));

参考文献:

《JavaScript模式》

《JavaScript设计模式与开发实践》

轻松掌握:JavaScript单例模式的更多相关文章

  1. javascript单例模式的理解

    javascript单例模式的理解 阅读目录 理解单例模式 使用代理实现单例模式 理解惰性单例 编写通用的惰性单例 单例模式使用场景 回到顶部 理解单例模式 单例模式的含义是: 保证一个类只有一个实例 ...

  2. 轻松学习 JavaScript——第 6 部分:JavaScript 箭头函数

    JavaScript箭头函数是ECMAScript 6中引入的编写函数表达式的一种简便方法.通常,在JavaScript中,可以通过两种方式创建函数: 函数语句. 函数表达式. 可以如下所示创建函数语 ...

  3. 浅析Javascript单例模式

    定义 保证一个类仅有一个实例,并提供一个访问它的全局访问点 .就想我们在开发中有些对象只需要一个,例如window对象. 1. 实现单例模式 var Singleton = function( nam ...

  4. [转] JavaScript 单例模式

    定义 确保一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式使用的场景 比如线程池.全局缓存等.我们所熟知的浏览器的window对象就是一个单例,在JavaScript开发中,对于这种只需要 ...

  5. 轻松学习JavaScript十八:DOM编程学习之DOM简单介绍

    一DOM概述 DOM(文档对象模型)是HTML和XML的应用程序接口(API).DOM将把整个页面规划成由节点层级构成的文档. DOM描绘了一个层次化的节点树,执行开发者加入,移除和改动页面的某一部分 ...

  6. Javascript单例模式概念与实例

    前言 和其他编程语言一样,Javascript同样拥有着很多种设计模式,比如单例模式.代理模式.观察者模式等,熟练运用Javascript的设计模式可以使我们的代码逻辑更加清晰,并且更加易于维护和重构 ...

  7. 轻松理解JavaScript闭包

    摘要 闭包机制是JavaScript的重点和难点,本文希望能帮助大家轻松的学习闭包 一.什么是闭包? 闭包就是可以访问另一个函数作用域中变量的函数. 下面列举出常见的闭包实现方式,以例子讲解闭包概念 ...

  8. 轻松理解JavaScript之AJAX

    摘要 AJAX技术是网页构建的必备技能之一,本文希望能帮助大家轻松的学习这项技术 一.什么是ajax? ajax(异步javascript xml) 能够刷新局部网页数据而不是重新加载整个网页. 二. ...

  9. 分针网—每日分享: 怎么轻松学习JavaScript

    js给初学者的印象总是那么的"杂而乱",相信很多初学者都在找轻松学习js的途径.   我试着总结自己学习多年js的经验,希望能给后来的学习者探索出一条"轻松学习js之路& ...

随机推荐

  1. 以Excel 作为Data Source,将data导入db

    将Excel作为数据源,将数据导入db,是SSIS的一个简单的应用,下图是示例Excel,数据列是code和name 第一部分,Excel中的数据类型是数值类型 1,使用SSDT创建一个package ...

  2. 把w3schools英文版的所有属性扒下来了,免费分享。

    为了方便查手册等,把w3schools上的所以属性弄成json版的了,到时候再修改一下,查起来就比较方便了,这里免费分享一下.一共为两份,一份为选择器部分,还有一部分是属性. 选择器部分json 属性 ...

  3. Android 设置对话框全屏

    1.在styles.xml中添加一个style: <style name="Dialog_Fullscreen"> <item name="androi ...

  4. Android搜索框效果

    转载:http://blog.csdn.net/walker02/article/details/7917392 需求:项目中的有关搜索的地方,加上清空文字的功能,目的是为了增加用户体验,使用户删除文 ...

  5. EntityFramework之摸索EF底层(八)

    前言 此篇文章我将深入去摸索edmx中一些不为人知的东西,有时候我们需要知道Code  First模型中一些存储以及映射的原理,个人觉得那是必要的也是有用的,因为很有可能SQL会出现一些其他问题,只有 ...

  6. Android标题栏最右边添加按钮

    step1:重写activity的onCreateOptionsMenu方法 @Override public boolean onCreateOptionsMenu(Menu menu){ Menu ...

  7. 解决FragmentTabHost切换标题栏变更问题

    现在都流行FragmentTabHost布局.但是所有的fragment都是共享一个actionbar,但是我们又想给每个fragment定义自定义的标题栏.百度google了好久也没有找到解决方案. ...

  8. 关于SubSonic3.0插件使用SubSonic.Query.Select查询时,字段类型为tinyint时列丢失问题的Bug修复

    下午在写代码时,突然发现一个列名为Enable的字段怎么也查询不出来,开始以为可能这个名称是关键字,所以给过滤掉了,所以就将名称修改为IsEnable,问题还是一样......将名称又改为IsEnab ...

  9. CodeIgniter笔记-去掉index.php

    1.修改Apache 的配置文件把LoadModule rewrite_module modules/mod_rewrite.so该行前的#去掉. 2.将 AllowOverride None ,修改 ...

  10. linux标准IO缓冲(apue)

    为什么需要标准IO缓冲? LINUX用缓冲的地方遍地可见,不管是硬件.内核还是应用程序,内核里有页高速缓冲,内存高速缓冲,硬件更不用说的L1,L2 cache,应用程序更是多的数不清,基本写的好的软件 ...