转载于原文地址:https://blog.csdn.net/q1056843325/article/details/52933426

举一个通俗的例子,在页面中点击登录按钮,弹出了一个登录浮窗,这个登录浮窗是唯一的,无论我们单击多少次,浮窗只会创建一次。

其实我们可能无意中都会使用过单例模式,我们的做法往往都是使用一个变量来标志当前是否已经为某个类创建了对象, 如果true,那么下一次再想获得这个类的实例时,直接返回之前创建过的对象。

单例模式的核心是确保只有一个实例,并提供全局访问。

其实在JavaScript中,单例模式并没有这么复杂

var a = {};

我们这样创建了对象a,它确实独一无二 
而且满足了单例模式的两个条件

  • 一个实例
  • 全局访问

但是全局变量很容易造成命名空间污染 ,如果项目很大的话,不小心覆盖了变量那就是致命的。

所以,在详细讲解这个单例模式之前,我们先来讨论这样一个问题,怎样降低全局污染? (全局污染也就是变量大量存在于全局作用域污染了全局空间 )

降低全局污染有两种办法:

1、使用命名空间

var namespace_payen = {
a: function(){
//...
}
b: function(){
//...
}
}

适当使用命名空间,并不会杜绝全局变量,但是可以减少全局变量的数量

2、使用闭包封装私有变量

var payen = (function(){
var _name = 'payson.Tsung',
_age = ;
return {
getInfo: function(){
return _name + ' ' + _age;
}
}
})();

变量被封装在了闭包内,只暴露一些接口用于外部通信,从而避免了对全局的命令污染

下面我来谈谈这个单例模式

先来个简单的例子

下面我声明了一个函数,每次调用都创建一个小方块

function createDiv(){
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '100px';
div.style.background = 'red';
div.style.marginBottom = '10px';
document.body.appendChild(div);
}
createDiv();
createDiv();
createDiv();

调用了三次,页面出现了三个小方块

下面我就使用单例模式,让它只创建一个div

var createDiv = (function(){
var div;
return function(){
if(!div){
div = document.createElement('div');
div.style.width = '100px';
div.style.height = '100px';
div.style.background = 'red';
div.style.marginBottom = '10px';
document.body.appendChild(div);
}
}
})();
createDiv();
createDiv();
createDiv();

再来看看页面,只有一个小方块

div声明在立即执行函数中作为私有变量 ,没有执行函数前, div值为undefined ,第一次执行函数时,判断div,如果没有,创建了一个DOM节点并且插入到了文档; 随后再执行函数时,div变量已经缓存了刚刚创建的DOM节点,不再创建 ,无论执行几次,小方块只会创建一次 ,这就是单例模式,而且是一个惰性单例。

惰性单例就是在需要的时候才创建对象实例,而非在页面加载时就创建 ,这样做的好处大家都知道。

虽然我们完成了惰性单例,但是我们同样发现了问题

  • 违反了单一职责原则,创建对象和管理单例放在了一个函数中createDiv
  • 如果我们还想创建一个其他的唯一对象,那就只能copy了

综上,我们需要把不变的部分隔离出来,把可变的封装起来,这给予了我们扩展程序的能力,符合“开放-封闭原则”;

下面我们就抽出管理单例的逻辑 ,无论怎样抽取,万变不离其中,用一个变量来标志是否创建过对象

var getSingle = function(fn){
var result;
return function(){
return result || (result = fn.apply(this, arguments));
}
};
var createDiv = function(){
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '100px';
div.style.background = 'red';
div.style.marginBottom = '10px';
document.body.appendChild(div);
return div;
};
var createSingleDiv = getSingle(createDiv);
createSingleDiv();
createSingleDiv();
createSingleDiv();

创建的DOM节点保存在了result中 ,result变量因为自身在闭包中,不会被销毁,如果result已经被赋值了,那么它将返回这个值 ;

单例模式很简单,而且也十分实用,他不仅仅用于创建对象,还有很多其他用途 ,比如说只绑定一次事件啦之类的

JS设计模式——单例模式剖析的更多相关文章

  1. js设计模式-单例模式

      JavaScript中的单例模式是最常用的.最基本的设计模式,它提供了一种命名空间,减少全局变量泛滥的代码管理机制: 1.最常见的单例模式: [javascript] view plain cop ...

  2. [js]js设计模式-单例模式

    单例模式 不同模块之间需要同时开发, // 单例模式: 把描述同一个事物的属性和方法放在同一个内存空间下. // 优点: 分组,防止冲突 // p1 p2也叫做命名空间(模块开发) var p1 = ...

  3. js 设计模式——单例模式

    单例模式 保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池.全局缓存.浏览器中的 window 对象等. JavaScript ...

  4. [转]JS设计模式-单例模式(二)

    单例模式是指保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的模式,有一些对象往往只需要一个,比如线程池.全局缓存.浏览器中的window对象等.在javaScript开发中 ...

  5. ES6教程-字符串,函数的参数,了解函数的arguments对象,js面向对象,设计模式-单例模式,解构赋值

    前言 主要讲解了ES6对字符串的拓展,包括includes,startsWith和endsWith,另外增加了字符串模板. Start includes()是否包含 startsWith()以什么开头 ...

  6. JS设计模式(一)

    刚入职时,看过一段时间的设计模式,似懂非懂.不知不觉过去七个月了,对JS的理解更深刻了,数据结构与算法的基础也基本上算是过了一遍了,接下来要把设计模式搞定,然后不再深层次研究JS了,而是学习前端自动化 ...

  7. JavaScript设计模式-单例模式、模块模式(转载 学习中。。。。)

    (转载地址:http://technicolor.iteye.com/blog/1409656) 之前在<JavaScript小特性-面向对象>里面介绍过JavaScript面向对象的特性 ...

  8. js设计模式总结1

    js设计模式有很多种,知道不代表会用,更不代表理解,为了更好的理解每个设计模式,对每个设计模式进行总结,以后只要看到总结,就能知道该设计模式的作用,以及模式存在的优缺点,使用范围. 本文主要参考张容铭 ...

  9. JS实现单例模式的多种方案

    JS实现单例模式的多种方案 今天在复习设计模式中的-创建型模式,发现JS实现单例模式的方案有很多种,稍加总结了一下,列出了如下的6种方式与大家分享 大体上将内容分为了ES5(Function)与ES6 ...

随机推荐

  1. 【数论&想法题】小C的问题 @"科林明伦杯"哈尔滨理工大学第八届程序设计竞赛

    Time Limit: 1000 MS Memory Limit: 256000 K Description 小C是一个可爱的女孩,她特别喜欢世界上最稳定的图形:三角形.有一天她得到了n根木棍,她把这 ...

  2. mysql 命令语句

    1.大部分数据库命令语句 数据库的命令 net start MYsql 启动的服务 net stop mysql 关闭服务 mysql -uroot -p 输入数据库名和密码登入 show datab ...

  3. C# Xamarin移动开发项目实战篇

    一.课程介绍 在前面阿笨的<C# Xamarin移动开发基础进修篇>课程中,大家已经熟悉和了解了Xamarin移动App开发的基础知识和原理.本次分享课<C# Xamarin移动开发 ...

  4. SharePoint 读取内容的插件之SharepointPlus

    前言 最近,一直在前端和SharePoint进行交互,然后,发现一个好用的插件,分享给大家. 首先,需要添加一个引用,如下图: 当然,我这里只是举个例子,亲们一定要去下载这个库,然后传到服务器或者文档 ...

  5. socket.io常用api

    1. 服务端 io.on('connection',function(socket)); 监听客户端连接,回调函数会传递本次连接的socket io.sockets.emit('String',dat ...

  6. [web 前端] mobx教程(一)-mobx简介

    opy from : https://blog.csdn.net/smk108/article/details/84777649 Mobx是通过函数响应式编程使状态管理变得简单和可扩展的状态管理库.M ...

  7. Github超棒资源汇总

    Awesome List 中文资源大全 经典编程书籍大全 免费的编程中文书籍索引 awesome-awesomeness-zh_CN https://github.com/jnv/lists awes ...

  8. Java代码质量监控工具Sonar安装

    1.  代码质量七宗罪 Sonar是一个代码质量管理系统.它的帮助文档开篇明义,提出了代码质量的七宗罪.总结的比較到位.最好还是一看: 1.        Bug和隐藏Bug(Bugs and Pot ...

  9. servlet的xx方式传值中文乱码

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOEx ...

  10. t-SNE 层次聚类

    https://zhuanlan.zhihu.com/p/28967965 https://haojunsui.github.io/2016/07/16/scipy-hac/