百度考题之单例模式

浅聊一下

设计模式是我们必不可少的编程素养,今天我们要聊的是百度考题------单例模式

es6新增 "类"

要讲单例模式,我们就从es6新增的类开始说起,我们先来看代码

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

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

console.log(s1 === s2);

这段代码定义了一个类,名字叫SingleDog,我们创建了两个SingleDog的实例对象s1和s2,打印一下他们的结果,这并不难理解,因为创建的s1和s2所存储的地址不同,他们是相同类的不同实例对象,于是乎,打印的结果肯定是 false

那么跟我们今天要讲的单例模式有什么关系呢?我们先来了解一下单例模式到底是什么...

单例模式

当我们谈论单例模式时,我们指的是一种设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来访问该实例。

什么意思?就是说在我上面的SingleDog类只能有一个实例对象,不管你创建了多少个对象,都会返回创建的第一个对象...那该咋办?我们得用到static

static

在 JavaScript 中,static 是一个关键字,用于定义类的静态属性和静态方法。静态成员属于类本身,而不是类的实例。

讲的这么深奥,我还是看不懂...那就直接上代码

js 复制代码
class SingleDog{
    //属于对象的
    show(){
        console.log('我是一个单例对象');
    
    }
    // 不要直接new 
    // 属于类的
    static getInstance(){
        console.log('静态方法');    
    }
}

当我们要使用show()方法时,我们得创建一个SingleDog的实例对象,然后再通过实例对象来调用show()方法

js 复制代码
const s1 = new SingleDog()
s1.show()

而当我们想要调用static方法的时候,不用创建直接调用

js 复制代码
SingleDog.getInstance()

实现单例模式

我们已经掌握了static,那么我们怎么来实现单例模式呢?

js 复制代码
class SingleDog{
    //属于对象的
    show(){
        console.log('我是一个单例对象');
    
    }
    // 不要直接new 
    // 属于类的
    static getInstance(){
        // console.log('静态方法');
        if(!SingleDog.instance){
            SingleDog.instance = new SingleDog();
        }
        return SingleDog.instance;
    }
}

static getInstance 是一个静态方法,它属于类本身而不是类的实例。通过 static 关键字声明的静态方法可以直接通过类名调用,无需创建类的实例。在这个例子中,getInstance 方法的作用是返回 SingleDog 类的一个实例。

  • getInstance 方法内部,首先检查静态属性 instance 是否已经存在实例。如果不存在,就创建一个新的 SingleDog 实例,并将其赋值给 instance 属性。
  • 随后,无论是否创建了新实例,都会返回 instance 属性的值,确保始终返回同一个实例。

通过这种设计,你可以确保 SingleDog 类的实例始终只有一个,因为 getInstance 方法在每次调用时都会返回相同的实例。这就是所谓的单例模式,它确保一个类只有一个实例,并提供了一个全局访问点以确保所有代码都在使用相同的实例。

使用静态方法来实现单例模式是一种常见的做法,因为它允许你在不创建实例的情况下访问类的方法,并且能够控制类的实例化过程。

百度考题-写一个弹窗

百度考题呀,让你写一个弹窗,实际上就是要你写一个单例模式,你点击一个按钮,弹出弹窗,点击关闭,弹窗关闭,无论你点击多少个按钮,无论你点击多少次按钮,弹窗始终是最开始的那个弹窗...

理解了上面讲的内容,想要写出来并不难

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录框</title>
    <style>
        #modal{
            width: 200px;
            height: 200px;
            background-color: #ccc;
            line-height: 200px;
            text-align: center;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
            border: 1px solid #000;          
        }
    </style>
</head>
<body>
    <button id="open">打开弹窗</button>
    <button id="close">关闭弹窗</button>
    <script>
        //立即执行函数
        // 闭包的方式实现单例
        const Modal = (function(){
            //创建闭包
            let modal = null//自由变量
            return function(){
                if(!modal){
                    modal = document.createElement('div')
                    modal.innerHTML = '我是全局唯一的登录框'
                    modal.style.display = 'none'
                    modal.id = 'modal'
                    document.body.appendChild(modal)
                }
                return modal
            }
        })()
        // const modal = new Modal()
        document.getElementById('open').addEventListener('click',function(){
            const modal = new Modal();
            modal.style.display = 'block'
        })
        document.getElementById('close').addEventListener('click',function(){
            const modal = new Modal();
            modal.style.display = 'none'
        })
    </script>
</body>
</html>
  1. 定义立即执行函数
js 复制代码
const Modal = (function(){ 
    // ... 
})()

这里定义了一个匿名函数,并立即执行它。由于括号 () 包裹在函数声明的外部,所以该函数会立即执行。同时,在函数内部定义了一个闭包,用于实现单例模式。

  1. 创建闭包
js 复制代码
let modal = null; 
return function() {
    // ... 
}

在闭包内部,定义了一个自由变量 modal,初始值为 null。然后,返回一个函数,该函数可以访问并操作 modal 变量,也就是实现了闭包。如果还有不会闭包的掘友可以去看我的文章(深入探讨:闭包的神秘面纱 - 掘金 (juejin.cn))

  1. 实现单例模式
js 复制代码
if (!modal) {
modal = document.createElement('div'); 
// ... 
return modal; 
}

在闭包内部的函数中,首先判断 modal 变量是否已经存在。如果不存在,则创建登录框元素,并将其添加到 body 中,然后将 modal 变量赋值为该元素。最后,返回 modal 变量。这样,下次再调用该函数时,就会直接返回之前创建的登录框元素,而不会重复创建。

  1. 使用单例模式
js 复制代码
document.getElementById('open').addEventListener('click', function() { 
const modal = new Modal(); 
modal.style.display = 'block'; 
}); 
document.getElementById('close').addEventListener('click', function() { 
const modal = new Modal();
modal.style.display = 'none'; 
});

在页面中,有两个按钮,一个用于打开登录框,一个用于关闭登录框。当用户点击打开按钮时,代码会调用 Modal 函数来获取或创建登录框元素,然后将其显示出来。当用户点击关闭按钮时,代码也调用 Modal 函数来获取或创建登录框元素,然后将其隐藏。

来看看效果:

点击打开弹窗,new了一个新的DOM结点,此时display为block

点击关闭弹窗,让DOM结点display为none

再次点击打开弹窗,不会新建一个DOM,而是让原来的DOMdisplay为block...题目完成

结尾

在实际应用中,合理地运用设计模式能够提高代码质量、可读性和可维护性,是每个开发者都应该掌握的技能之一。希望本篇内容能对你有所帮助,如果有任何疑问或者想继续探讨其他主题,都可以随时提出哦!

相关推荐
uhakadotcom1 小时前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
范文杰1 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪2 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪2 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy2 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom3 小时前
快速开始使用 n8n
后端·面试·github
uhakadotcom3 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom3 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom3 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom3 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试