过完年了,让我们一起学习前端设计模式

过年假期已经接近尾声了,很多小伙伴是不是一样,准备返程搬砖了呢?今年过年跟往年也没有不一样,也就是在家吃吃喝喝,逗逗娃(侄子侄女),走走亲戚。本来今年想着不回老家的,怕被父母亲戚催婚,但后面想想今年家里房子刚装修,也想回去看看,另外也想吃到爸妈做的饭菜,还是回去了。可没曾想今年一个相亲对象都没给我介绍,说是去年介绍的被我谈崩了,老家已经没得适龄女青年了,不知道是喜是悲。

老家镇上买的新房(拒绝当房奴,实际上是穷)

一直有在掘金上看掘金小册的习惯,陆陆续续买了十几本,但真正看完就两三本。春节期间看完了《JavaScript 设计模式核心原理与应用实践》,想着拿前端比较常见的几种设计模式总结一下。

前端设计模式之一:单例模式

单例模式属于前端设计模式中创建型的一种,我们常见的前端状态管理工具Vuex和Redux都是采用单例模式,来实现了一个全局的 Store 用于存储应用的所有状态。当然它们具体的实现细节肯定不完全一样,但无疑都是应用了单例模式的思想。

单例模式的实现思路

一般情况下,当我们创建了一个类(本质是构造函数)后,可以通过new关键字调用构造函数进而生成任意多的实例对象。像这样:

javascript 复制代码
class SingleDog {
    show() {
        console.log('我是一个单例对象')
    }
}

const s1 = new SingleDog()
const s2 = new SingleDog()

// false
s1 === s2

但现在我们要思考这样一个问题:如何才能保证一个类仅有一个实例?

要做到这一点,就需要构造函数具备判断自己是否已经创建过一个实例的能力。我们现在把这段判断逻辑写成一个静态方法:

javascript 复制代码
class SingleDog {
    show() {
        console.log('我是一个单例对象')
    }
    static getInstance() {
        // 判断是否已经new过1个实例
        if (!SingleDog.instance) {
            // 若这个唯一的实例不存在,那么先创建它
            SingleDog.instance = new SingleDog()
        }
        // 如果这个唯一的实例已经存在,则直接返回
        return SingleDog.instance
    }
}

const s1 = SingleDog.getInstance()
const s2 = SingleDog.getInstance()

// true
s1 === s2

除了楼上这种实现方式之外,getInstance的逻辑还可以用闭包来实现:

javascript 复制代码
function SingleDogBase() {}SingleDogBase.prototype.show = function() {  console.log('我是一个单例对象')}
const SingleDog = (function() {
    // 定义闭包变量
    let instance = null
    return function() {
        if(!instance) {
            // 创建实例
            instance = new SingleDogBase()
        }
        return instance
    }
})()

const s1 = new SingleDog()const s2 = new SingleDog()

// ture
s1 === s2

可以看出,在已经创建的实例instance的判断和拦截下,我们不管调用多少次,SingleDog都只会给我们返回一个实例,s1和s2现在都指向这个唯一的实例。

单例模式应用之一:实现一个全局模态框

学会了单例如何创建,接下来让我们实现一个全局的模态框。

完整代码如下:

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单例模式弹框</title>
</head>
<style>
    #modal {
        height: 200px;
        width: 200px;
        line-height: 200px;
        position: fixed;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        border: 1px solid black;
        text-align: center;
    }
</style>
<body>
	<button id='open'>打开弹框</button>
	<button id='close'>关闭弹框</button>
</body>
<script>
    // 核心逻辑,这里采用了闭包思路来实现单例模式
    const Modal = (function() {
    	let modal = null
    	return function() {
            if(!modal) {
            	modal = document.createElement('div')
            	modal.innerHTML = '我是一个全局唯一的Modal'
            	modal.id = 'modal'
            	modal.style.display = 'none'
            	document.body.appendChild(modal)
            }
            return modal
    	}
    })()
    
    // 点击打开按钮展示模态框
    document.getElementById('open').addEventListener('click', function() {
        // 未点击则不创建modal实例,避免不必要的内存占用
    	const modal = new Modal()
    	modal.style.display = 'block'
    })
    
    // 点击关闭按钮隐藏模态框
    document.getElementById('close').addEventListener('click', function() {
    	const modal = new Modal()
    	if(modal) {
    	    modal.style.display = 'none'
    	}
    })
</script>
</html>

ES6 版本:

lua 复制代码
// class的静态方法实现  class Modal {    static getInstance() {      if (!Modal.instance) {        Modal.instance = document.createElement('div')        Modal.instance.innerHTML = '我是全局唯一的Modal'        Modal.instance.id = 'modal'        Modal.instance.style.display = 'none'        document.body.appendChild(Modal.instance)      }      return Modal.instance    }    static open() {      Modal.getInstance().style.display = 'block'    }    static close() {      Modal.getInstance().style.display = 'none'    }  }  const openBtn = document.getElementById('open')  const closeBtn = document.getElementById('close')  openBtn.addEventListener('click', function() {    Modal.open()  })  closeBtn.addEventListener('click', function() {    Modal.close()  })

以上代码大部分是小册的原代码,心里还有些忐忑是不是太水。但转念想想,对于自己算一种加深巩固,如果对掘友也能提供一点帮助,那也算一点贡献。有兴趣的同学可以购买大佬的小册深入学习一下,绝对是物有所值的。

小册地址:JavaScript 设计模式核心原理与应用实践 - 修言 - 掘金小册 (juejin.cn)

相关推荐
zhougl99620 分钟前
html处理Base文件流
linux·前端·html
花花鱼24 分钟前
node-modules-inspector 可视化node_modules
前端·javascript·vue.js
HBR666_27 分钟前
marked库(高效将 Markdown 转换为 HTML 的利器)
前端·markdown
careybobo2 小时前
海康摄像头通过Web插件进行预览播放和控制
前端
TDengine (老段)2 小时前
TDengine 中的关联查询
大数据·javascript·网络·物联网·时序数据库·tdengine·iotdb
杉之3 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
喝拿铁写前端3 小时前
字段聚类,到底有什么用?——从系统混乱到结构认知的第一步
前端
再学一点就睡3 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
木木黄木木5 小时前
html5炫酷图片悬停效果实现详解
前端·html·html5
请来次降维打击!!!5 小时前
优选算法系列(5.位运算)
java·前端·c++·算法