单例模式1定义保证一个类只有一个实例,并提供一个全局访问点来访问它。2应用时机当一个类的实例被频繁使用时,如果重复创建这个实例,会无缘无故地消耗资源。比如dialog弹窗会被全局复用。业务功能本身决定了全局只能有一个唯一的实例。比如redux管理的数据只能有一个唯一的副本。3应用场景对于前端应用的很多基础组件:如dialog、message等,这些都是全局频繁使用的,需要维护一个全局唯一的实例,避免重复创建造成不必要的资源消耗。业务组件也是如此:比如购物车组件、登录弹窗组件等。对于一些通用的工具库,往往会采用单例模式。比如我们通常会创建一个全局唯一的axios实例来发起网络请求。对于redux、vuex等状态管理库,使用一个全局唯一的store来存储应用状态数据等。4代码实现4.1全局变量和命名空间都是基于single定义的example模式//维护类A类的唯一实例A{}window.a=newA();//或global.a=newA();浏览器使用window的方式存在明显的缺陷,因为同一个项目中的所有程序员都可以定义一个全局变量a,这样很容易造成全局污染。解决方法是设置自己的命名空间,区别于别人//比如我设置自己的命名空间JiMingwindow.JiMing={a:newA()}如果使用TypeScript,可以使用关键字namespacenamespaceJiMing{exportconsta=newA();}4.2Lazysingleton在上面的实现中,我们直接在全局创建一个类A的单实例,不管是否使用,在某些场景下会造成资源浪费。有时候我们想在需要的时候创建一个实例下面的代码使用了立即执行函数和闭包来获取A的单例获取函数:getSingletonOfAclassA{}constgetSingletonOfA=(()=>{letinstance;return()=>{return(instance??=newA());};})();只有在调用getSingletonOfA时才会创建A的实例,并将其存储在闭包中的实例中。重复调用getSingletonOfA会得到相同的一个实例consta1=getSingletonOfA();consta2=getSingletonOfA();console.log(a1===a2);//true上述方法可以满足单例模式,但不够通用,改造如下constcreateSingletonUtil=(className)=>{letinstance;return()=>{return(instance??=newclassName());};};我们封装了一个工具函数createSingletonUtil,调用这个函数后,我们可以得到任意类的“单例获取函数”a3===a4);//truecreateSingletonUtil的TypeScript实现如下:classA{}constcreateSingletonUtil=
