利用ES6实现单例模式及其应用详解


Posted in Javascript onDecember 09, 2017

前言

在传统开发工程师眼里,单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。

单例模式的定义是:保证一个类仅有一个一个实例,并提供一个访问它的全局访问点。

单例模式能在合适的时候创建对象,并且创建唯一的一个。

代码接近于生活,很有意思。比如一个网站的登录,点击登录后弹出一个登录弹框,即使再次点击,也不会再出现一个相同的弹框。又或者一个音乐播放程序,如果用户打开了一个音乐,又想打开一个音乐,那么之前的播放界面就会自动关闭,切换到当前的播放界面。这些都是单例模式的应用场景。

要实现一个单例模式,一个经典的方式是创建一个类,类中又一个方法能创建该类的实例对象,还有一个标记,记录是否已经创了过了实例对象。如果对象已经存在,就返回第一次实例化对象的引用。

单例模式的实现

es5实现方式

var Singleton = function(name) {
 this.name = name;
 //一个标记,用来判断是否已将创建了该类的实例
 this.instance = null;
}
// 提供了一个静态方法,用户可以直接在类上调用
Singleton.getInstance = function(name) {
 // 没有实例化的时候创建一个该类的实例
 if(!this.instance) {
  this.instance = new Singleton(name);
 }
 // 已经实例化了,返回第一次实例化对象的引用
 return this.instance;
}

用户可以通过一个广为人知的接口,对该实例进行访问。

我们尝试对该对象进行两次实例化,观察两次实例化结果是否指向同一个对象。

var a = Singleton.getInstance('sven1');
var b = Singleton.getInstance('sven2');
// 指向的是唯一实例化的对象
console.log(a === b);

返回结果是:true。说明a、b之间是引用关系。

es6实现方式

创建Singleton类。class关键字和静态函数都是es6新增的。

class Singleton {
 constructor(name) {
  this.name = name;
  this.instance = null;
 }
 // 构造一个广为人知的接口,供用户对该类进行实例化
 static getInstance(name) {
  if(!this.instance) {
   this.instance = new Singleton(name);
  }
  return this.instance;
 }
}

单例模式应用实例

我们用一个生活中常见的一个场景来说明单例模式的应用。

任意一个网站,点击登录按钮,只会弹出有且仅有一个登录框,即使后面再点击登录按钮,也不会再弹出多一个弹框。这就是单例模式的典型应用。接下来我们实现它。为了注重单例模式的展示,我们把登录框简化吧?

在页面上设置一个按钮

<button id="loginBtn">登录</button>

为这个按钮添加点击事件

const btn = document.getElementById('loginBtn');
btn.addEventListener('click', function() {
 loginLayer.getInstance();
}, false);

我们先给一个初始化方法init,在点击按钮之后,在页面上添加一个框框(权当登录框了)

init() {
 var div = document.createElement('div');
 div.classList.add('login-layer');
 div.innerHTML = "我是登录浮窗";
 document.body.appendChild(div);
}

那么接下来要用单例模式实现,点击按钮出现有且仅有一个浮窗,方法就是在构造函数中创建一个标记,第一次点击时创建一个浮窗,用改变标记的状态,再次点击按钮时,根据标记的状态判断是否要再创建一个浮窗。

上源码:

class loginLayer {
 constructor() {
  // 判断页面是否已有浮窗的标记
  this.instance = null;
  this.init();
 }
 init() {
  var div = document.createElement('div');
  div.classList.add('login-layer');
  div.innerHTML = "我是登录浮窗";
  document.body.appendChild(div);
 }
 // 静态方法作为广为人知的接口
 static getInstance() {
  // 根据标记的状态判断是否要再添加浮窗,如果标记不为空就创建一个浮窗
  if(!this.instance) {
   this.instance = new loginLayer();
  }
  return this.instance;
 }
}

当然不要忘记为浮窗添加一个样式,让浮窗显示啦

.login-layer {
 width: 200px;
 height: 200px;
 background-color: rgba(0, 0, 0, .6);
 text-align: center;
 line-height: 200px;
 display: inline-block;
}

最后奉上该实例的源码:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>单例实现登录弹窗</title>
 <style>
  .login-layer {
   width: 200px;
   height: 200px;
   background-color: rgba(0, 0, 0, .6);
   text-align: center;
   line-height: 200px;
   display: inline-block;
  }
 </style>
</head>
<body>
 <button id="loginBtn">登录</button>
 <script>
  const btn = document.getElementById('loginBtn');
  btn.addEventListener('click', function() {
   loginLayer.getInstance();
  }, false);  
  class loginLayer {
   constructor() {
    this.instance = null;
    this.init();
   }
   init() {
    var div = document.createElement('div');
    div.classList.add('login-layer');
    div.innerHTML = "我是登录浮窗";
    document.body.appendChild(div);
   }
   static getInstance() {
    if(!this.instance) {
     this.instance = new loginLayer();
    }
    return this.instance;
   }
  }
 </script>
</body>
</html>

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
ASP中用Join和Array,可以加快字符连接速度的代码
Aug 22 Javascript
jQuery弹出层插件简化版代码下载
Oct 16 Javascript
jquery 卷帘效果实现代码(不同方向)
Feb 05 Javascript
javascript 数组排序函数sort和reverse使用介绍
Nov 21 Javascript
JQUERY dialog的用法详细解析
Dec 19 Javascript
javascript写的异步加载js文件函数(支持数组传参)
Jun 07 Javascript
JS实现很酷的水波文字特效实例
Feb 26 Javascript
jQuery插件Validate实现自定义表单验证
Jan 18 Javascript
详解angular中的作用域及继承
May 31 Javascript
react-native-tab-navigator组件的基本使用示例代码
Sep 07 Javascript
JS+CSS3实现的简易钟表效果示例
Apr 13 Javascript
使用Typescript和ES模块发布Node模块的方法
May 25 Javascript
利用node.js如何创建子进程详解
Dec 09 #Javascript
微信小程序使用slider设置数据值及switch开关组件功能【附源码下载】
Dec 09 #Javascript
微信小程序实现action-sheet弹出底部菜单功能【附源码下载】
Dec 09 #Javascript
微信小程序使用toast消息对话框提示用户忘记输入用户名或密码功能【附源码下载】
Dec 09 #Javascript
微信小程序loading组件显示载入动画用法示例【附源码下载】
Dec 09 #Javascript
Angular中点击li标签实现更改颜色的核心代码
Dec 08 #Javascript
Javascript中的作用域及块级作用域
Dec 08 #Javascript
You might like
深入PHP autoload机制的详解
2013/06/09 PHP
php中让上传的文件大小在上传前就受限制的两种解决方法
2013/06/24 PHP
ThinkPHP查询中的魔术方法简述
2014/06/25 PHP
php array_values 返回数组的所有值详解及实例
2016/11/12 PHP
PHP实现从PostgreSQL数据库检索数据分页显示及根据条件查找数据示例
2018/06/09 PHP
PHP实现腾讯短网址生成api接口实例
2020/12/08 PHP
网页自动刷新,不产生嗒嗒声的一个解决方法
2007/03/27 Javascript
(仅IE下有效)关于checkbox 三态
2007/05/12 Javascript
javascript 模拟点击广告
2010/01/02 Javascript
javaScript call 函数的用法说明
2010/04/09 Javascript
jquery的ajax和getJson跨域获取json数据的实现方法
2014/02/04 Javascript
js分页代码分享
2014/04/28 Javascript
基于BootStrap的图片轮播效果展示实例代码
2016/05/23 Javascript
Bootstrap页面布局基础知识全面解析
2016/06/13 Javascript
原生态js,鼠标按下后,经过了那些单元格的简单实例
2016/08/11 Javascript
微信小程序 Template详解及简单实例
2017/01/05 Javascript
js根据json数据中的某一个属性来给数据分组的方法
2018/10/08 Javascript
基于纯JS实现多张图片的懒加载Lazy过程解析
2019/10/14 Javascript
js编写简易的计算器
2020/07/29 Javascript
用smtplib和email封装python发送邮件模块类分享
2014/02/17 Python
浅谈五大Python Web框架
2017/03/20 Python
简单谈谈Python中的元祖(Tuple)和字典(Dict)
2017/04/21 Python
Python实现简单的语音识别系统
2017/12/13 Python
django中上传图片分页三级联动效果的实现代码
2019/08/30 Python
python3反转字符串的3种方法(小结)
2019/11/07 Python
python爬虫开发之urllib模块详细使用方法与实例全解
2020/03/09 Python
美国领先的精品家居照明和装饰产品在线零售商:LightsOnline.com
2018/01/23 全球购物
教育学习自我评价
2014/02/03 职场文书
《我不是最弱小的》教学反思
2014/02/23 职场文书
保密工作目标责任书
2014/07/28 职场文书
公司捐书倡议书
2015/04/27 职场文书
辞职信格式范文
2015/05/13 职场文书
债务纠纷代理词
2015/05/25 职场文书
《惊弓之鸟》教学反思
2016/02/20 职场文书
css实现两栏布局,左侧固定宽,右侧自适应的多种方法
2021/08/07 HTML / CSS
电脑关机速度很慢怎么办 提升电脑关机速度设置教程
2022/04/08 数码科技