JS实现单例模式的多种方案

简介: 今天在复习设计模式中的-创建型模式,发现JS实现单例模式的方案有很多种,稍加总结了一下,列出了如下的6种方式与大家分享大体上将内容分为了ES5(Function)与ES6(Class)实现两种部分

JS实现单例模式的多种方案


今天在复习设计模式中的-创建型模式,发现JS实现单例模式的方案有很多种,稍加总结了一下,列出了如下的6种方式与大家分享


大体上将内容分为了ES5(Function)与ES6(Class)实现两种部分


单例模式的概念


  • 一个实例只生产一次
  • 保证一个类仅有一个实例,并提供一个访问它的全局访问点


方式1


利用instanceof判断是否使用new关键字调用函数进行对象的实例化


function User() {
    if (!(this instanceof User)) {
        return
    }
    if (!User._instance) {
        this.name = '无名'
        User._instance = this
    }
    return User._instance
}
const u1 = new User()
const u2 = new User()
console.log(u1===u2);// true


方式2


在函数上直接添加方法属性调用生成实例


function User(){
    this.name = '无名'
}
User.getInstance = function(){
    if(!User._instance){
        User._instance = new User()
    }
    return User._instance
}
const u1 = User.getInstance()
const u2 = User.getInstance()
console.log(u1===u2);


方式3


使用闭包,改进方式2


function User() {
    this.name = '无名'
}
User.getInstance = (function () {
    var instance
    return function () {
        if (!instance) {
            instance = new User()
        }
        return instance
    }
})()
const u1 = User.getInstance()
const u2 = User.getInstance()
console.log(u1 === u2);


方式4


使用包装对象结合闭包的形式实现


const User = (function () {
    function _user() {
        this.name = 'xm'
    }
    return function () {
        if (!_user.instance) {
            _user.instance = new _user()
        }
        return _user.instance
    }
})()
const u1 = new User()
const u2 = new User()
console.log(u1 === u2); // true


当然这里可以将闭包部分的代码单独封装为一个函数


在频繁使用到单例的情况下,推荐使用类似此方法的方案,当然内部实现可以采用上述任意一种


function SingleWrapper(cons) {
    // 排除非函数与箭头函数
    if (!(cons instanceof Function) || !cons.prototype) {
        throw new Error('不是合法的构造函数')
    }
    var instance
    return function () {
        if (!instance) {
            instance = new cons()
        }
        return instance
    }
}
function User(){
    this.name = 'xm'
}
const SingleUser = SingleWrapper(User)
const u1 = new SingleUser()
const u2 = new SingleUser()
console.log(u1 === u2);


方式5


在构造函数中利用new.target判断是否使用new关键字


class User{
    constructor(){
        if(new.target !== User){
            return
        }
        if(!User._instance){
            this.name = 'xm'
            User._instance = this
        }
        return User._instance
    }
}
const u1 = new User()
const u2 = new User()
console.log(u1 === u2);


方式6


使用static静态方法


class User {
    constructor() {
        this.name = 'xm'
    }
    static getInstance() {
        if (!User._instance) {
            User._instance = new User()
        }
        return User._instance
    }
}
const u1 = User.getInstance()
const u2 = User.getInstance()
console.log(u1 === u2);


相关文章
|
7月前
|
存储 JavaScript 前端开发
Vuex详解:Vue.js的状态管理方案
Vuex详解:Vue.js的状态管理方案
64 1
|
JavaScript 定位技术
原生 js 实现类 3d 地图大屏展示自动高亮轮播、显示悬浮提示 tootip 的方案:svg + popper.js 定位引擎
原生 js 实现类 3d 地图大屏展示自动高亮轮播、显示悬浮提示 tootip 的方案:svg + popper.js 定位引擎
256 0
原生 js 实现类 3d 地图大屏展示自动高亮轮播、显示悬浮提示 tootip 的方案:svg + popper.js 定位引擎
|
9月前
|
消息中间件 JavaScript 前端开发
js异步处理方案,js的异步串行与异步并行
js异步处理方案,js的异步串行与异步并行
67 0
|
5月前
|
设计模式 存储 JavaScript
js设计模式之单例模式
js设计模式之单例模式
49 7
|
10月前
|
前端开发 JavaScript Serverless
前端工程化的前端性能的性能优化方案的渲染层面优化之CSS/JS优化
渲染是一种非常重要的前端性能优化方案,因为它可以在不同的环境中提高网页的响应速度和可接受性。
64 2
|
9月前
|
JavaScript 前端开发
说说你对JavaScript模块化方案的理解和 CommonJS、AMD、CMD、ES6 Module 分别是什么?
模块化是指将一个复杂问题,自顶向下逐层把系统划分为若干模块的过程。对于整个系统来说,这些模块可组合,分解和更换的单元。对于编程领域的模块化就是遵守固定的原则,将一个大文件拆分成多个独立且相互依赖的小模块。简单理解模块化就是在一个js文件中能够引入另一个js文件
|
10月前
|
设计模式 JavaScript 前端开发
|
11月前
|
缓存 JavaScript
javaScript_单例模式
javaScript_单例模式
38 0
|
11月前
|
监控 前端开发 JavaScript
React CSS-In-JS 方案 : Linaria Vs Styled-Components
在开发一个 React 应用时,其中一个比较大的挑战就是为应用选择一个合适的样式处理方案。因为我们需要考虑到样式的可维护性,开发体验,以及样式对应用性能的影响等
157 0
React CSS-In-JS 方案 :  Linaria Vs Styled-Components
|
11月前
|
JavaScript 前端开发 索引
leetcode.328奇偶链表——Javascript实现方案
leetcode.328奇偶链表——Javascript实现方案
67 0