JS设计模式——单例模式剖析
转载于原文地址: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设计模式——单例模式剖析的更多相关文章
- js设计模式-单例模式
JavaScript中的单例模式是最常用的.最基本的设计模式,它提供了一种命名空间,减少全局变量泛滥的代码管理机制: 1.最常见的单例模式: [javascript] view plain cop ...
- [js]js设计模式-单例模式
单例模式 不同模块之间需要同时开发, // 单例模式: 把描述同一个事物的属性和方法放在同一个内存空间下. // 优点: 分组,防止冲突 // p1 p2也叫做命名空间(模块开发) var p1 = ...
- js 设计模式——单例模式
单例模式 保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池.全局缓存.浏览器中的 window 对象等. JavaScript ...
- [转]JS设计模式-单例模式(二)
单例模式是指保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的模式,有一些对象往往只需要一个,比如线程池.全局缓存.浏览器中的window对象等.在javaScript开发中 ...
- ES6教程-字符串,函数的参数,了解函数的arguments对象,js面向对象,设计模式-单例模式,解构赋值
前言 主要讲解了ES6对字符串的拓展,包括includes,startsWith和endsWith,另外增加了字符串模板. Start includes()是否包含 startsWith()以什么开头 ...
- JS设计模式(一)
刚入职时,看过一段时间的设计模式,似懂非懂.不知不觉过去七个月了,对JS的理解更深刻了,数据结构与算法的基础也基本上算是过了一遍了,接下来要把设计模式搞定,然后不再深层次研究JS了,而是学习前端自动化 ...
- JavaScript设计模式-单例模式、模块模式(转载 学习中。。。。)
(转载地址:http://technicolor.iteye.com/blog/1409656) 之前在<JavaScript小特性-面向对象>里面介绍过JavaScript面向对象的特性 ...
- js设计模式总结1
js设计模式有很多种,知道不代表会用,更不代表理解,为了更好的理解每个设计模式,对每个设计模式进行总结,以后只要看到总结,就能知道该设计模式的作用,以及模式存在的优缺点,使用范围. 本文主要参考张容铭 ...
- JS实现单例模式的多种方案
JS实现单例模式的多种方案 今天在复习设计模式中的-创建型模式,发现JS实现单例模式的方案有很多种,稍加总结了一下,列出了如下的6种方式与大家分享 大体上将内容分为了ES5(Function)与ES6 ...
随机推荐
- NodeJS缓冲区
NodeJS缓冲区 JavaScript语言本身在I/O时只有字符串数据类型,没有二进制数据类型,但在处理流数据时,必须用到二进制数据,因此在Node中,定义了一个Buffer类作为存放二进制数据的缓 ...
- Build fails with an error: Execution failed for task ':react-native-google-analytics-bridge:compileDebugJavaWithJavac'.
1,问题 Build fails with an error: Execution failed for task ':react-native-google-analytics-bridge:com ...
- 11-13 js操作css样式
1.Js操作css样式 Div.style.width=”100px”.在div标签内我们添加了一个style属性,并设定了width值.这种写法会给标签带来大量的style属性,跟实际项目是不符. ...
- JS膏集04
JS膏集04 1.apply和call方法 可以改变this的指向,可以用于函数的调用 apply和call方法中如果没有传入参数,或者传入null,那么调用该方法的函数中的this就是window ...
- Codefoces909E Coprocessor(拓扑排序)
http://codeforces.com/problemset/problem/909/E 由于分了两个queue,所以push的时候可以统一操作,不会影响彼此.两个queue相当于是平等的,只是q ...
- ssh以root用户远程登录失败
参考文献: http://blog.csdn.net/lichangzai/article/details/39379153 http://blog.csdn.net/yasi_xi/article/ ...
- MediaInfo代码阅读
MediaInfo是一个用来分析媒体文件的开源工具. 支持的文件非常全面,基本上支持所有的媒体文件. 最近是在做HEVC开发,所以比较关注MediaInfo中关于HEVC的分析与处理. 从Meid ...
- Asp.Net 自定义设置Http缓存示例(一)
一.自定义图片输出,启用客户端的图片缓存处理 代码示例: string path = Request.Url.LocalPath; if (path != null) { path = path.To ...
- 深度残差网络(DRN)ResNet网络原理
一说起“深度学习”,自然就联想到它非常显著的特点“深.深.深”(重要的事说三遍),通过很深层次的网络实现准确率非常高的图像识别.语音识别等能力.因此,我们自然很容易就想到:深的网络一般会比浅的网络效果 ...
- 如何将excel 数据库表结构生成powerdesign物理模型
Option Explicit Dim mdl ' the current model Set mdl = ActiveModel If (mdl Is Nothing) Then MsgBox &q ...