Самый простой способ реализации Singleton в JavaScript

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для эффективного создания синглтона в JavaScript используйте IIFE (немедленно вызываемое функциональное выражение). Оно скрывает ссылку на единственный экземпляр класса и предоставляет метод для получения этого экземпляра. Таким образом, Singleton.getInstance() всегда возвращает один и тот же объект, что гарантирует его уникальность во всем приложении.

JS
Скопировать код
const Singleton = (function() {
  let instance;
  function createInstance() {
    // Здесь находятся закрытые переменные, обращайтесь с уважением!
    const secret = 'Singleton';
    const whisper = () => { console.log('Здесь могла быть ваша реклама'); };
    return {
      // Открытые методы и свойства
      spillBeans: whisper
    };
  }
  return {
    getInstance: function() {
      // Лень – двигатель прогресса!
      if (!instance) {
        instance = createInstance();
        // Замораживаем объект, чтобы сохранить его аутентичность
        Object.freeze(instance);
      }
      return instance;
    }
  };
})();

// Пример использования
const example1 = Singleton.getInstance();
const loneWolf = Singleton.getInstance();

console.log(example1 === loneWolf); // true, и только ему одному!
Кинга Идем в IT: пошаговый план для смены профессии

Укрепляем синглтон: пути повышения надежности

Рассмотрим несколько эффективных способов улучшения надежности синглтона:

Применение классов ES6 со статическим свойством

Использование классов ES6 придает синглтону актуальность и стиль. Приватные поля можно "спрятать" за #, а уникальность экземпляра гарантируется статическим методом:

JS
Скопировать код
class Singleton {
  static instance;
  #secretData = 'Singleton';

  constructor() {
    // Подобно 'кольцу всевластья'
    if (Singleton.instance) {
      return Singleton.instance;
    }
    Singleton.instance = this;
  
    // Можно заморозить экземпляр: холодный как лед, надежный как скала
    Object.freeze(this);
  }
  
  spillBeans() {
    console.log(this.#secretData);
  }
}

Каждый новый экземпляр окажется все тем же надежным синглтоном, раскрывающим секреты через свои границы:

JS
Скопировать код
// Пример использования
const test1 = new Singleton();
const test2 = new Singleton();

console.log(test1 === test2); // true, все за одного и один за всех!

Модули ES6: идеальные спутники синглтона

Модули ES6 – это идеальное дополнение для синглтона, как арахисовое масло к джему. Экспортируйте экземпляр через модуль, и везде, где он будет импортирован, он останется тем же самым:

JS
Скопировать код
// В файле singleton.js
const Singleton = {
  secret: 'Singleton',
  whisper() { console.log('Ожидаем магического персонажа'); }
};

// Заморозим объект на века
Object.freeze(Singleton);

export default Singleton;

В каждом импорте вы встретите всегда того же верного синглтона:

JS
Скопировать код
// Синглтон будет непоколебим как в Хогвартсе, так и в Шире!
import Singleton from './singleton';

Визуализация

Представьте себе VIP-ложу в концертном зале 🎶 — самое лучшее место среди всех. Оно уникально, как единорог (👑), первоначальный занимающий имеет непререкаемое право на внимание (💃), остальным же говорят: "Мест нет!" (🚫).

Точно также работает и синглтон:

Markdown
Скопировать код
const concertHall = {
  vipSeat: null
};
  
function claimVIPSeat(visitor) {
  // Заполучить VIP-место — это всегда испытание!
  if (!concertHall.vipSeat) {
    concertHall.vipSeat = visitor;
    console.log(visitor + " занял VIP-место! Ура!");
  } else {
    console.log("Извините, " + visitor + ", но VIP-место уже занято.");
  }
}

claimVIPSeat('Alice'); // Алиса стала владелицей VIP-места!
claimVIPSeat('Bob'); // Боб, к сожалению, место уже занято.

Особенность синглтона: одно место, много претендентов, но победитель только один!

Обращайте внимание: потокобезопасность и ленивая инициализация в синглтоне

Преимущества паттерна синглтон идут вместе с такими рисками, как проблемы потокобезопасности и ленивой инициализации. JavaScript работает в однопоточной модели, что создает особые задачи при работе с асинхронными процесами. Промисы и async/await помогают изящно манипулировать ими при работе со синглтоном.

IIFE изначально обеспечивает ленивую инициализацию, гарантируя создание единственного экземпляра только тогда, когда это действительно нужно, что позволяет экономить ресурсы.

Когда 'один' – это слишком: осознание проблем паттерна синглтона

Синглтон может казаться простым решением для доступа к общим ресурсам, но часто такой подход приводит к злоупотреблению паттерном и трансформации его в антипаттерн. Чрезмерное использование синглтона может вызвать проблемы с доступом к ресурсам и сложности при модульном тестировании из-за трудностей управления состоянием.

Всегда помните о возможных рисках при работе с синглтонами и используйте их рассудительно!

Полезные материалы

  1. Object.freeze() – JavaScript | MDN – Узнайте больше о "замораживании" объектов.
  2. Converting Singleton JS objects to use ES6 classes – Stack Overflow — Обсуждение перевода синглтонов на классы ES6 на Stack Overflow.
  3. JavaScript Design Patterns: The Singleton — SitePoint — Полная информация о синглтонах и их особенностях.
  4. Private Members in JavaScript — Подробно о приватных свойствах в JavaScript от Crockford.
  5. Learning JavaScript Design Patterns — Поиск святого грааля среди паттернов – Синглтон.
  6. Medium — Рассуждения о синглтонах в контексте ES6.
  7. [The Revealing Module Pattern – Learning JavaScript Design Patterns [Book]](https://www.oreilly.com/library/view/learning-javascript-design/9781449334840/ch09s03.html) — Глубокое погружение в мир модульных паттернов.
Свежие материалы