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,未必是如何呈现的吗? web浏览器根据地址栏中指定的url,从web服务器获取文件资源(resource)等信息,从而显示出web页面。web使用HTTP(…...
可靠的可视化监控平台应用在那些场景?
可视化监控平台是一种用户友好的工具,可以帮助用户实时监控IT设备的运行状态和网络流量,以及监测安全性和性能指标。它们通常采用图形化界面,使得用户能够直观地了解设备和网络的状态。 以下是一些可视化监控平台常见的应用场景:…...
从 BBR 失速到带宽探测
看一下 pacing 流失速的成因: 一段时间收不到 ack,丢了 ack 自时钟,cwnd 将耗尽,bbr 虽有 cwnd_gain(上图没有表现),但在该 cwnd_gain 下不依赖 ack 持续坚持发送多久取决于 cwnd_gain 的数值。 bbr 失速的后果在于…...
MobaXterm使用sz/rz命令下载上传文件
MobaXterm使用sz/rz命令下载上传文件 1 参考文档2 下载3 上传 1 参考文档 MobaXterm使用sz/rz命令下载上传文件 2 下载 步骤1:sz filename 步骤2:ctrl 鼠标右键 步骤3:Receive file using Z-modem 3 上传 步骤1:rz 步骤2&am…...
vue el-popover hover延时触发,el-popover 鼠标放上三秒以后触发
背景:el-popover hover只要鼠标刮过就显示 多个el-popover出现加载卡顿 解决方案 给el-popover加一个延时显示 <template><div><el-popovertrigger"hover":open-delay"3000"content"这是一个Popover"><button…...
计算机竞赛 基于深度学习的人脸识别系统
前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学习的人脸识别系统 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/…...
Android扫码连接WIFI实现
0,目标 APP中实现扫WIFI分享码自动连接WIFI功能 1,前提条件 设备需要有个扫码器(摄像头拍照识别也行),APP调用扫码器读取WIFI连接分享码。 2,增加权限 在AndroidManifest.xml中增加权限 <uses-permissi…...
TrOCR – 基于 Transformer 的 OCR 入门指南
多年来,光学字符识别 (OCR) 出现了多项创新。它对零售、医疗保健、银行和许多其他行业的影响是巨大的。尽管有着悠久的历史和多种最先进的模型,研究人员仍在不断创新。与深度学习的许多其他领域一样,OCR 也看到了变压器神经网络的重要性和影响。如今,我们拥有像TrOCR(Tran…...
MAC终端美化
先看看效果: 1.安装on-my-zsh 打开终端,输出: sh -c "$(curl -fsSL https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh)"安装过程中如果出现了链接超时的错误,不要慌,就再来一次&#x…...
Matlab常用字符串操作教程
Matlab是一种功能强大的编程语言,它提供了丰富的字符串操作函数。在本教程中,我们将介绍一些常用的Matlab字符串操作函数和用法。 字符串的创建和访问: 使用单引号或双引号创建字符串:str Hello World; 或 str "Hello Worl…...
基于SSM的汽车养护管理系统
末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…...
Redis发布订阅机制学习
【IT老齐151】Redis发布订阅机制是如何实现的?_哔哩哔哩_bilibili go-redis的发布与订阅 - 知乎 (zhihu.com) 前置: 先输入 redis-server.exe 启动redis,否则对应接口不开放 再输入 redis-cli 命令启动客户端服务 1.机制示意图 当一…...
施展世界:GPT时代需要的教育,是学会如何提出好问题
来源:BV1co4y1W7h7 有很多脑力活,它实际上是伪装成脑力活的体力活,它在回答问题这个层面,那是非常的厉害,人现在肯定是比不过它了,注意了,这是回答问题的层面,但问题是谁来问问题呢&…...
Excel学习 WPS版
Excel学习 1.界面基础1.1 方格移动快捷键1.2 自动适配文字长度1.3 跨栏置中1.4 多个单元格同宽度: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. 从性能焦虑到精准定位:为什么需要全链路压测? 第一次接手移动应用性能优化项目时,我盯着监控大屏上跳动的红色警报线手足无措。用户投诉像雪片般飞来:"支付页面卡死"、"图片加载转圈半分钟"、"活动页…...
每天140万亿次“Token“在狂奔!这组数据背后,有人赚疯,有人焦虑到失眠
> 就在今天,你刷的每一条AI回复,都在创造历史。0101 你随口的一句话,正在"吃掉"一座超级计算机你有没有这种感觉——早上用豆包写了个周报,中午让Kimi帮你总结了一份PDF,下午在微信里让AI画了一张插画&am…...
多模式MRI数据融合显示帕金森病患者抑郁的结构、功能和神经化学相关
论文总结1、研究问题:帕金森病中抑郁症非常常见,但机制复杂,既涉及脑结构异常,也涉及脑功能异常,还可能涉及多种神经递质系统。且现有研究大多是基于单模态,只看结构或者只看功能,很少研究“结构…...
LLM长文本处理实战:模块化分割策略与向量化预处理指南
1. 项目概述:一个为LLM打造的文本处理中心如果你和我一样,经常和大型语言模型打交道,无论是用它来总结文档、分析代码,还是处理客服对话,那你肯定遇到过这个痛点:喂给模型的文本太长了怎么办?模…...
Task GCP终极指南:如何在谷歌云平台上实现高效任务调度与自动化构建 [特殊字符]
Task GCP终极指南:如何在谷歌云平台上实现高效任务调度与自动化构建 🚀 【免费下载链接】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调用熔断机制
更多请点击: https://intelliparadigm.com 第一章:Spring Boot项目接入Claude的3种生产级方案,含安全沙箱、审计日志与LLM调用熔断机制 在高可用AI服务场景中,将Claude大模型能力安全、可控、可观测地集成进Spring Boot应用&…...
基于GitHub Actions的AI智能体部署指南:exoclaw-github实战解析
1. 项目概述:在GitHub里养一只会看代码的“螃蟹”如果你在GitHub上维护过开源项目,肯定遇到过这样的场景:新开的Issue描述不清,得来回问好几轮才能定位问题;PR提交上来,你得逐行审阅代码,既费时…...
API集成管理之核心产品核心能力与数据盘点
API集成管理是企业数字化转型中的核心基础设施,它解决的是系统之间如何高效、安全、可控地进行数据交换与业务协同的问题。一套完善的API集成管理方案,能够帮助企业打通数据孤岛、实现能力复用、构建开放生态。本文基于公开资料,对五款代表性…...
华为会议转任务AI精准识别整理,省事更清晰,轻松搞定工作落地
"找2026华为会议转任务AI的朋友,你要的精准识别整理、落地工作的真实测评来了。不管你是做学术研究要整访谈、转讲座,还是开会长音频要扒任务,我测了大半个月,直接给你掏实底。我接触太多做学术的朋友,都踩过AI转…...
统一AI编程助手配置:使用agent-anatomy提升开发效率与一致性
1. 项目概述:一个配置文件夹,统一所有AI编程助手如果你和我一样,日常开发中会同时使用Claude Code、Cursor、GitHub Copilot等多个AI编程助手,那你一定也经历过同样的烦恼:每个助手都需要自己独立的配置文件。今天要介…...
