如何在 JavaScript 中使用单例

介绍

是最知名的设计模式之一。有时您只需要一个类的实例,仅此而已。这一类可以是某种资源管理器或某种值的全局查找。这就是单身人士的用武之地。

在本文中,您将了解什么是单例以及如何在 JavaScript 中最好地实现它们。

先决条件

要成功完成本教程,您需要具备以下条件:

  • 对 JavaScript 编码的理解。如果您需要进一步扩展您在该领域的知识,请查看此JavaScript 系列
  • 了解类在 JavaScript 中的工作方式。这个理解 JavaScript 中的类教程可以提供这一点。

理解单身人士

单例用于创建一个不存在的类的实例,否则返回现有实例的引用。这意味着在应用程序运行期间在全局范围内只创建一次单例。

基于这个定义,单例看起来与全局变量非常相似。您可能想知道为什么应该在具有全局变量的编码语言中使用单例。有一些事情使单例与全局变量不同:

  • 全局变量是词法范围的,而单例不是。这意味着如果在编程块内还有另一个与全局变量同名的变量,则优先考虑第一个引用。但是,单身人士不应重新声明该引用。
  • 单例的值是通过方法修改的。
  • 单例在程序终止之前不会被释放,这可能不是全局变量的情况。

即使在支持全局变量的语言中,单例也非常有用。有些情况下单例很方便。单例的一些应用是记录器对象或配置设置类。

声明单身人士

有几种方法可以声明单例。这是您可能会看到的一种格​​式:

var SingletonInstance = {
 method1: function () { ... }
 method2: function () { ... }
};

这个单身人士会像这样被记录到控制台:

console.log(SingletonInstance.method1());
console.log(SingletonInstance.method2());

最好记住,这不是声明单例的最佳方式。另一种方法是使用一次创建单例的工厂类。

var SingletonFactory = (function(){
  function SingletonClass() {
    // ...
  }

  var instance;

  return {
    getInstance: function(){
      if (!instance) {
        instance = new SingletonClass();
        delete instance.constructor;
      }
      return instance;
    }
  };
})();

这是第一个示例的更好替代方案,因为类定义是私有的,并且在创建第一个实例后删除了构造函数。这将防止在程序中创建重复的单例。这种方法的缺点是它与工厂模式非常相似。

还有第三种方法。这种方法实现了 ES6 类和Object.freeze()方法的组合

脚本.js
class Singleton {
  constructor() {
   // ...
  }

  method1() {
    // ...
  }

  method2() {
    // ...
  }
}

const singletonInstance = new Singleton();

Object.freeze(singletonInstance);

Object.freeze()方法防止修改对象的属性和值。因此,应用Object.freeze()singletonInstance意味着您以后将无法在代码中更改其任何属性或值。

您可以更进一步,将此单例编写为一个模块,并使用 ES6 导出功能将其导出:

脚本.js
export default singletonInstance;

然后这个单例可以通过导入在一个单独的文件中使用:

其他文件.js
import mySingleton from './script.js';

mySingleton.method1();

使用这三种创建单例的方法,选择最适合您的特定用例的方法,以实现高可读性。

结论

在 JavaScript 代码中使用单例并不总是必要的。在不影响应用程序状态的地方使用单例。这种限制严重限制了它们在大型应用程序中的使用。

使用工具包中的这种基本设计模式,您可能想探索JavaScript 中的工厂模式如果你有兴趣了解更多关于状态的管理,检查出这些文章的状态管理与终极版作出反应,并与之反应钩状态管理

觉得文章有用?

点个广告表达一下你的爱意吧 !😁