深入理解 JavaScript 單例模式 (Singleton Pattern)

来源:https://www.cnblogs.com/gaoguowen/archive/2019/07/22/11228177.html
-Advertisement-
Play Games

概念 單例模式,也叫單子模式,是一種常用的軟體設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。 核心:確保只有一個實例,並提供全局訪問。 實現思路 一個類能返回對象一個引用(永遠是同一個)和一個獲得該實例的方法(必須是靜態方法,通常命名為 );當我們調用這個方法時,類持有的引用不為 ...


概念

單例模式,也叫單子模式,是一種常用的軟體設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。

核心:確保只有一個實例,並提供全局訪問。

實現思路

一個類能返回對象一個引用(永遠是同一個)和一個獲得該實例的方法(必須是靜態方法,通常命名為getIntance);當我們調用這個方法時,類持有的引用不為空則返回這個引用,如果為空須創建該類實例並將實例的引用賦予該類保持的引用;同時將該類的構造函數定義為私有方法,那麼其他環境就無法通過調用該類的構造函數來實例化該類的對象,只能通過該類提供的靜態方法得到該類唯一的實例。

實現 Java 語言中的單例模式

  public class Singleton {
      private static final Singleton {
          private Singleton() { };

          public static Singleton getInstance {
              if (INSTANCE == null) {
                  synchronized(Singleton.class) {
                      if(INSTANCE = null) {
                         INSTANCE = new Singleton()
                      }
                  }

              }
              return INSTANCE;
          }
      }
  }

實現 JavaScript 語言中的單例模式

let Singleton = function(name){
    this.name = name;
}
Singleton.prototype.getName = function() {
    console.log(this.name)
}
Singleton.getInstance = (function() {
   let instance;
   return function(name) {
       if(instance) return instance;
       return instance = new Singleton(name)
   }
})()
let s1 = Singleton.getInstance('owen'); // Singleton {name: "owen"}
let s2 = Singleton.getInstance('guowen'); // Singleton.getInstance('guowen');
s1 === s2 // true

JavaScript中單例作為一個命名空間提供者,從全局命名空間里提供一個唯一的訪問點來訪問該對象。

應用

命名空間

使用命名空間可以降低全局變數帶來的命名污染;
最簡單的方法是對象字面量

const globalWeb = {
    a() {},
    b() {}
    // ...
}

或者使用閉包

let Singleton = (function(){
    let instance;
    let init = function() {
    let name = 'owen';
        return {
            name,
            data(){
                return {}
            },
            method:{ }
        }
    }
    return {
        getInstance() {
            if(instance) return instance;
            return instance = init()
        }
    }
}())
let app = Singleton.getInstance() // {name: "owen", data: ƒ, method: {…}}

惰性單例

惰性單例指在需要的時候才創建對象實例,在實現開發中非常有用,即目標對象只有在使用的時候才被創建,而不是頁面載入好時創建。

模態框示例

點擊一個按鈕彈窗一個模態框,很明顯頁面是唯一的,一次不會彈窗多個模態框的情況

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>modal box</title>
    <style>
    * {
        margin: 0;
        padding:0;
    }
   html{
   width:100%;
   height:100%;
   }
    .Owen {
        width:30%;
        height:30%;
        margin:10% auto;
    }
    #modal {
        width:100%;
        height:100%;
        position:fixed;
        left:0;
        top:0;
        background: rgba(0, 0, 0, 0.52);
        display:none;
    }
    .main{
        width:30%;
        height:30%;
        margin:10% auto;
        text-align: center;
        background-color: #b0e8ff;
    }
    </style>
</head>
<body>
   <div class="Owen">
        <button>Owen</button>
   </div>
    <div id="modal">
        <div class="main">
          <div>
                我是彈框
          </div>
        </div>
    </div>
</body>
<script>

window.onload = function(){
    let openModal = document.querySelector("button")
    let modal = document.querySelector("#modal")
    openModal.addEventListener('click',function(){
       modal.style.display = 'block'
    })
}

</script>
</html>

第一種方法是在頁面載入完成時創建好這個彈框,一開始就是隱藏的,只有點擊按鈕的時候才顯示,這種方式有一個問題,就是我們進入頁面,只是看看其他內容,不做任何操作;這樣就造成資源浪費

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>modal box</title>
    <style>
    * {
        margin: 0;
        padding:0;
    }
   html{
   width:100%;
   height:100%;
   }
    .Owen {
        width:30%;
        height:30%;
        margin:10% auto;
    }
    #modal {
        width:100%;
        height:100%;
        position:fixed;
        left:0;
        top:0;
        background: rgba(0, 0, 0, 0.52);
    }
    .main{
        width:30%;
        height:30%;
        margin:10% auto;
        padding:20px;
        text-align: right;
        background-color: #b0e8ff;
        position:relative;
    }
    .main div {
        text-align: center;
    }
    .main span {
        display: inline-block;
        padding:5px;
        cursor:pointer;
    }
    </style>
</head>
<body>

    <div class="Owen">
        <button>點我</button>
    </div>

</body>
<script>
window.onload = function(){
    init()
}
function init() {
    let openModal = document.querySelector("button")
    let createModal =( function() {
        let flag;
        // 生成 Modal 容器
        let div = document.createElement('div')
        div.id = "modal"
        div.style.display = "none";
        return function() {
            if(flag) return div;
            flag = true;
            let fra = document.createDocumentFragment();
            // 添加 Modal 內容
            els = `<div class="main">
                    <span class="close">×</span>
                        <div>
                            我是彈框
                        </div>
                    </div>
                    `
            div.innerHTML = els;
            fra.appendChild(div)
            document.body.appendChild(fra)
            // 關閉 Modal
            let close = document.querySelector('.close')
            close.addEventListener('click',function(){
                flag = false;
                document.body.removeChild(div)
            })

            return div
        }
    }())
    // 顯示 Modal
    openModal.addEventListener('click',function(){
       createModal().style.display = "block";
    })
}
</script>
</html>

第二種方法,只執行一次DOM的創建修改操作,不用頻繁的創建和刪除節點,提高資源利用率;

個人博客

參考資料

《JavaScript設計模式與開發實踐》
基維

大叔


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • "消息隊列內部實現原理" "兩種消息傳輸方式" "Kafka" "kafka 簡介" "kafka 集群角色" "Kafka 工作流程分析" "Kafka 生產過程分析" "寫入方式" "分區(partition)" "副本(replication)" "寫入數據" "Broker 保存消息" "存 ...
  • 達內全套前端視頻教程,包括js,h5,css3等,如果打不開,請聯繫本人,可重新分享 下載地址 ...
  • 後端路由:對於普通的網站,所有的超鏈接都是URL地址,所有的URL地址都對應伺服器上對應的資源 前端路由:對於單頁面應用程式來說,主要通過URL中的hash(#號)來實現不同頁面之間的切換(不會刷新頁面),同時,hash有一個特點:HTTP請求中不會包含hash相關的內容;所以,單頁面程式中的頁面跳 ...
  • 記錄一下使用項目中使用EasyUI遇到的bug,廢話少說直接上菜 - _-(bug)。。。。。 bug :: .netcore創建一個web應用時候,會自動引入jQuery庫以及一些插件,但是在使用EasyUI裡面的tree組件時,他會報一個錯,運行時候點擊F12即可顯示出來:.tree() is ...
  • CSS水平垂直居中 1 絕對定位 + 轉換 2 彈性模型 3 單元格方式 ...
  • npm install lib-flexible --save npm install px2rem-loader --save-dev rule .use('px2rem-loader') .loader('px2rem-loader') .options({emUnit:37.5}) 正常移動端 ...
  • 一、HTTP協議概述 HTTP是一個簡單的請求-響應協議,屬於應用層的面向對象的協議,由於其簡捷、快速的方式,適用於分散式超媒體信息系統。它通常運行在TCP之上。它指定了客戶端發送給伺服器什麼樣的消息得到什麼樣的響應。 二、HTTP協議的主要特點可概括如下: 1.B/S結構(Browser/Serv ...
  • *在js中不同類型之間的運算,所得到結果的類型也會有所變化: string + number = string string + boolean = string string + undefiend = string number + boolean = number number + undef ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...