当前位置: 首页 > news >正文

JavaScript单例模式

JavaScript单例模式

  • 1 什么是单例模式
  • 2 实现一个基础的单例模式
  • 3 透明的单例模式
  • 4 用代理实现单例模式
  • 5 JavaScript 中的单例模式
  • 6 惰性单例

1 什么是单例模式

保证一个类只有一个实例,并提供一个访问它的全局访问点,这就是单例模式。

单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如window对象、全局缓存等。

2 实现一个基础的单例模式

根据单例模式的特点,在实现单例模式时,我们要保证某个类只能创建一个实例对象,那么实现的基本思路就是:用一个变量标识当前是都已经为某个类创建过对象,如果是,在下一次获取该类的实例时,直接返回之前创建的对象,否则创建一个新对象,示例代码如下:

// 定义一个构造函数MyExample,定义属性name与instance
function MyExample(name) {this.name = name;this.instance = null;
}
// 在原型上定义getName方法
MyExample.prototype.getName = function () {console.log(this.name);
};
// 为构造函数定义getInstance方法,用来获取类的实例
MyExample.getInstance = function (name) {// 标识是否创建了实例,如果没有,赋值为新的实例,如果已经创建,返回原来的实例if (!this.instance) {this.instance = new MyExample(name);}return this.instance;
};// 为MyExample类创建实例,看似创建两个实例,实际上都是同一个实例
var e1 = MyExample.getInstance("example1");
var e2 = MyExample.getInstance("example2");console.log(e1 === e2); // true

我们通过MyExample.getInstance来获取 MyExample类的唯一对象,这种方式相对简单,但有一个问题,就是增加了这个类的“不透明性”,MyExample类的使用者必须知道这是一个单例类,跟以往通过new XXX的方式来获取对象不同。

3 透明的单例模式

在上一步中,由于该类的“不透明性”,用户在使用时会有一些困难,因此在本节中实现一个“透明”的单例类,让用户在使用这个类创建对象时,可以和使用其他普通类一样。

接下来实现一个单例类CreateDiv,这个类的作用是在页面创建唯一的div节点,代码如下:

var CreateDiv = (function () {var instance; // 标识是否创建过实例// 创建CreateDiv类var CreateDiv = function (html) {// 如果已经创建过实例,返回当前实例if (instance) {return instance;}// 如果没有创建实例。创建一个div元素,并返回this.init();this.html = html;return (instance = this);};// 定义init方法,目的是创建一个div元素,元素内容由我们自己定义CreateDiv.prototype.init = function () {var div = document.createElement("div");div.innerHTML = this.html;document.body.appendChild(div);};return CreateDiv;
})();var e1 = new CreateDiv("example1");
var e2 = new CreateDiv("example2");console.log(e1 === e2); // true

虽然现在完成了一个透明的单例类的编写,但它同样有一些缺点,为了把instance封装起来,使用了自执行的匿名函数和闭包,并且让这个匿名函数返回真正的构造方法,复杂度高,可读性也变差了。

4 用代理实现单例模式

在上面的例子中,假设我们某天需要利用这个类,在页面中创建千千万万的div,即要让这个类从单例类变成一个普通的可产生多个实例的类,那我们必须得改写CreateDiv构造函数,这种修改会给我们带来不必要的烦恼,因此我们通过引入代理类的方式来解决这个问题

首先在CreateDiv构造函数中,把负责管理单例的代码提出来,使它成为一个普通的创建div的类:

var CreateDiv = function (html) {this.html = html;this.init();
};CreateDiv.prototype.init = function () {var div = document.createElement("div");div.innerHTML = this.html;document.body.appendChild(div);
};

接下来引入代理类proxySingletonCreateDiv

var ProxySingletonCreateDiv = (function () {var instance;return function (html) {if (!instance) {instance = new CreateDiv(html);}return instance;};
})();var e1 = new ProxySingletonCreateDiv("example1");
var e2 = new ProxySingletonCreateDiv("example2");console.log(e1 === e2); // true

上面的例子通过引入代理类的方式完成了一个单例模式的改写,与之前不同的是,现在把负责管理单例的逻辑移到了代理类proxySingletonCreateDiv中。这样一来,CreateDiv就变成了一个普通的类,它跟 proxySingletonCreateDiv组合起来可以达到单例模式的效果。

5 JavaScript 中的单例模式

前面提到的几种单例模式的实现,更多的是接近传统面向对象语言中的实现,单例对象从“类”中创建而来,在以类为中心的语言中,这是很自然的做法。比如在Java中,如果需要某个对象,就必须先定义一个类,对象总是从类中创建而来的。

JavaScript其实是一门无类语言,创建对象的方法非常简单,既然我们只需要一个“唯一”的对象,为什么要为它先创建一个“类”呢,传统的单例模式实现在JavaScript中并不适用。

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

全局变量不是单例模式,但在JavaScript开发中,我们经常会把全局变量当成单例来使用。例如:

var a = {}; 

当用这种方式创建对象a时,对象a确实是独一无二的。如果a变量被声明在全局作用域下,我们可以在代码中的任何位置使用这个变量,这样就满足了单例模式的两个条件。但是全局变量存在很多问题,它很容易造成命名空间污染。

我们可以采用以下几种方式降低全局变量带来的命名污染:

1、使用命名空间,适当地使用命名空间,并不会杜绝全局变量,但可以减少全局变量的数量,最简单的方法依然是用对象字面量的方式:

var namespace1 = {a: function () {alert(1);},b: function () {alert(2);},
};

2、使用闭包封装私有变量,这种方法把一些变量封装在闭包的内部,只暴露一些接口跟外界通信:

var user = (function () {var __name = "sven",__age = 29;return {getUserInfo: function () {return __name + "-" + __age;},};
})();

我们用下划线来约定私有变量__name__age,它们被封装在闭包产生的作用域中,外部是访问不到这两个变量的,这就避免了对全局的命令污染。

6 惰性单例

惰性单例指的是在需要的时候才创建对象实例。

惰性单例是单例模式的重点,实例对象instance总是在我们调用MyExample.getInstance的时候才被创建,而不是在页面加载好的时候就创建,示例代码如下:

MyExample.getInstance = (function () {var instance = null;return function (name) {if (!instance) {instance = new MyExample(name);}return instance;};
})();

相关文章:

JavaScript单例模式

JavaScript单例模式 1 什么是单例模式2 实现一个基础的单例模式3 透明的单例模式4 用代理实现单例模式5 JavaScript 中的单例模式6 惰性单例 1 什么是单例模式 保证一个类只有一个实例,并提供一个访问它的全局访问点,这就是单例模式。 单例模式是一种常…...

centos下安装jenkins.war

https://get.jenkins.io/war-stable/ 下载jenkins.war包,(2.164.1 版本支持1.8,其他的都是jdk11),可以安装完成后更新jenkins.war的安装包启动jenkins命令 java -jar jenkins.war --httpPort8010访问http://IP:8010/jenkins (密码在/root/.jenkins/secre…...

App线上网络问题优化策略

在我们App开发过程中,网络是必不可少的,几乎很难想到有哪些app是不需要网络传输的,所以网络问题一般都是线下难以复现,一旦到了用户手里就会碰到很多疑难杂症,所以对于网络的监控是必不可少的,针对用户常见…...

PDF 工具箱

PDF 工具箱 V9.0.0.1 程序:VB.net 运行库:NET Framework 4.5 功能简介: 1、PDF文件多文件合并,可调整顺序。 2、PDF文件拆分,将每页拆分成独立的PDF文件。 3、PDF文件添加水印,文字或图片水印&…...

大数据组件系列-Hadoop每日小问

1、谈谈对HDFS的理解?HDFS这种存储适合哪些场景? HDFS即Hadoop Distributed File System,Hadoop 分布式文件系统。它为的是解决海量数据的存储与分析的问题,它本身是源于Google在大数据方面的论文,GFS-->HDFS; HD…...

【前端】在Vue页面中引入其它vue页面 数据传输 相互调用方法等

主页面 home 从页面 headView 需求 在 home.vue 中引用 headView.Vue 方案: home.vue 代码: 只需要在home.vue 想要的地方添加 <headView></headView> <script>//聊天页面 import headView /view/headView.vueexport default {components: {headView},…...

网络通信深入解析:探索TCP/IP模型

http协议访问web 你知道在我们的网页浏览器的地址当中输入url&#xff0c;未必是如何呈现的吗&#xff1f; web浏览器根据地址栏中指定的url&#xff0c;从web服务器获取文件资源&#xff08;resource&#xff09;等信息&#xff0c;从而显示出web页面。web使用HTTP&#xff08…...

可靠的可视化监控平台应用在那些场景?

可视化监控平台是一种用户友好的工具&#xff0c;可以帮助用户实时监控IT设备的运行状态和网络流量&#xff0c;以及监测安全性和性能指标。它们通常采用图形化界面&#xff0c;使得用户能够直观地了解设备和网络的状态。 以下是一些可视化监控平台常见的应用场景&#xff1a;…...

从 BBR 失速到带宽探测

看一下 pacing 流失速的成因&#xff1a; 一段时间收不到 ack&#xff0c;丢了 ack 自时钟&#xff0c;cwnd 将耗尽&#xff0c;bbr 虽有 cwnd_gain(上图没有表现)&#xff0c;但在该 cwnd_gain 下不依赖 ack 持续坚持发送多久取决于 cwnd_gain 的数值。 bbr 失速的后果在于…...

MobaXterm使用sz/rz命令下载上传文件

MobaXterm使用sz/rz命令下载上传文件 1 参考文档2 下载3 上传 1 参考文档 MobaXterm使用sz/rz命令下载上传文件 2 下载 步骤1&#xff1a;sz filename 步骤2&#xff1a;ctrl 鼠标右键 步骤3&#xff1a;Receive file using Z-modem 3 上传 步骤1&#xff1a;rz 步骤2&am…...

vue el-popover hover延时触发,el-popover 鼠标放上三秒以后触发

背景&#xff1a;el-popover hover只要鼠标刮过就显示 多个el-popover出现加载卡顿 解决方案 给el-popover加一个延时显示 <template><div><el-popovertrigger"hover":open-delay"3000"content"这是一个Popover"><button…...

计算机竞赛 基于深度学习的人脸识别系统

前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的人脸识别系统 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/…...

Android扫码连接WIFI实现

0&#xff0c;目标 APP中实现扫WIFI分享码自动连接WIFI功能 1&#xff0c;前提条件 设备需要有个扫码器&#xff08;摄像头拍照识别也行&#xff09;&#xff0c;APP调用扫码器读取WIFI连接分享码。 2&#xff0c;增加权限 在AndroidManifest.xml中增加权限 <uses-permissi…...

TrOCR – 基于 Transformer 的 OCR 入门指南

多年来,光学字符识别 (OCR) 出现了多项创新。它对零售、医疗保健、银行和许多其他行业的影响是巨大的。尽管有着悠久的历史和多种最先进的模型,研究人员仍在不断创新。与深度学习的许多其他领域一样,OCR 也看到了变压器神经网络的重要性和影响。如今,我们拥有像TrOCR(Tran…...

MAC终端美化

先看看效果&#xff1a; 1.安装on-my-zsh 打开终端&#xff0c;输出&#xff1a; sh -c "$(curl -fsSL https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh)"安装过程中如果出现了链接超时的错误&#xff0c;不要慌&#xff0c;就再来一次&#x…...

Matlab常用字符串操作教程

Matlab是一种功能强大的编程语言&#xff0c;它提供了丰富的字符串操作函数。在本教程中&#xff0c;我们将介绍一些常用的Matlab字符串操作函数和用法。 字符串的创建和访问&#xff1a; 使用单引号或双引号创建字符串&#xff1a;str Hello World; 或 str "Hello Worl…...

基于SSM的汽车养护管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

Redis发布订阅机制学习

【IT老齐151】Redis发布订阅机制是如何实现的&#xff1f;_哔哩哔哩_bilibili go-redis的发布与订阅 - 知乎 (zhihu.com) 前置&#xff1a; 先输入 redis-server.exe 启动redis&#xff0c;否则对应接口不开放 再输入 redis-cli 命令启动客户端服务 1.机制示意图 当一…...

施展世界:GPT时代需要的教育,是学会如何提出好问题

来源&#xff1a;BV1co4y1W7h7 有很多脑力活&#xff0c;它实际上是伪装成脑力活的体力活&#xff0c;它在回答问题这个层面&#xff0c;那是非常的厉害&#xff0c;人现在肯定是比不过它了&#xff0c;注意了&#xff0c;这是回答问题的层面&#xff0c;但问题是谁来问问题呢&…...

Excel学习 WPS版

Excel学习 1.界面基础1.1 方格移动快捷键1.2 自动适配文字长度1.3 跨栏置中1.4 多个单元格同宽度&#xff1a;1.5 下拉框选择1.6 打印预览1.7 绘制边框1.8 冻结一行多行表头1.9 分割视图 2.日期相关2.1 今日日期快捷键2.2 月份提取 3.数学公式3.1 自动增长3.2 排序3.3 筛选3.4 …...

实战 | 性能瓶颈无处遁形,揭秘 mPaaS 全链路压测的落地策略与调优秘籍

1. 从性能焦虑到精准定位&#xff1a;为什么需要全链路压测&#xff1f; 第一次接手移动应用性能优化项目时&#xff0c;我盯着监控大屏上跳动的红色警报线手足无措。用户投诉像雪片般飞来&#xff1a;"支付页面卡死"、"图片加载转圈半分钟"、"活动页…...

每天140万亿次“Token“在狂奔!这组数据背后,有人赚疯,有人焦虑到失眠

> 就在今天&#xff0c;你刷的每一条AI回复&#xff0c;都在创造历史。0101 你随口的一句话&#xff0c;正在"吃掉"一座超级计算机你有没有这种感觉——早上用豆包写了个周报&#xff0c;中午让Kimi帮你总结了一份PDF&#xff0c;下午在微信里让AI画了一张插画&am…...

多模式MRI数据融合显示帕金森病患者抑郁的结构、功能和神经化学相关

论文总结1、研究问题&#xff1a;帕金森病中抑郁症非常常见&#xff0c;但机制复杂&#xff0c;既涉及脑结构异常&#xff0c;也涉及脑功能异常&#xff0c;还可能涉及多种神经递质系统。且现有研究大多是基于单模态&#xff0c;只看结构或者只看功能&#xff0c;很少研究“结构…...

LLM长文本处理实战:模块化分割策略与向量化预处理指南

1. 项目概述&#xff1a;一个为LLM打造的文本处理中心如果你和我一样&#xff0c;经常和大型语言模型打交道&#xff0c;无论是用它来总结文档、分析代码&#xff0c;还是处理客服对话&#xff0c;那你肯定遇到过这个痛点&#xff1a;喂给模型的文本太长了怎么办&#xff1f;模…...

Task GCP终极指南:如何在谷歌云平台上实现高效任务调度与自动化构建 [特殊字符]

Task GCP终极指南&#xff1a;如何在谷歌云平台上实现高效任务调度与自动化构建 &#x1f680; 【免费下载链接】task A fast, cross-platform build tool inspired by Make, designed for modern workflows. 项目地址: https://gitcode.com/gh_mirrors/ta/task 在现代化…...

Spring Boot项目接入Claude的3种生产级方案,含安全沙箱、审计日志与LLM调用熔断机制

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Spring Boot项目接入Claude的3种生产级方案&#xff0c;含安全沙箱、审计日志与LLM调用熔断机制 在高可用AI服务场景中&#xff0c;将Claude大模型能力安全、可控、可观测地集成进Spring Boot应用&…...

基于GitHub Actions的AI智能体部署指南:exoclaw-github实战解析

1. 项目概述&#xff1a;在GitHub里养一只会看代码的“螃蟹”如果你在GitHub上维护过开源项目&#xff0c;肯定遇到过这样的场景&#xff1a;新开的Issue描述不清&#xff0c;得来回问好几轮才能定位问题&#xff1b;PR提交上来&#xff0c;你得逐行审阅代码&#xff0c;既费时…...

API集成管理之核心产品核心能力与数据盘点

API集成管理是企业数字化转型中的核心基础设施&#xff0c;它解决的是系统之间如何高效、安全、可控地进行数据交换与业务协同的问题。一套完善的API集成管理方案&#xff0c;能够帮助企业打通数据孤岛、实现能力复用、构建开放生态。本文基于公开资料&#xff0c;对五款代表性…...

华为会议转任务AI精准识别整理,省事更清晰,轻松搞定工作落地

"找2026华为会议转任务AI的朋友&#xff0c;你要的精准识别整理、落地工作的真实测评来了。不管你是做学术研究要整访谈、转讲座&#xff0c;还是开会长音频要扒任务&#xff0c;我测了大半个月&#xff0c;直接给你掏实底。我接触太多做学术的朋友&#xff0c;都踩过AI转…...

统一AI编程助手配置:使用agent-anatomy提升开发效率与一致性

1. 项目概述&#xff1a;一个配置文件夹&#xff0c;统一所有AI编程助手如果你和我一样&#xff0c;日常开发中会同时使用Claude Code、Cursor、GitHub Copilot等多个AI编程助手&#xff0c;那你一定也经历过同样的烦恼&#xff1a;每个助手都需要自己独立的配置文件。今天要介…...