453 Stimmen

Einfachste / sauberste Möglichkeit, ein Singleton in JavaScript zu implementieren

Was ist der einfachste/sauberste Weg, um das Singleton-Muster in JavaScript zu implementieren?

34 Stimmen

Downvote dafür, dass die akzeptierte Antwort überhaupt kein Singleton ist. Es ist einfach eine globale Variable.

7 Stimmen

Dies ist eine Menge Informationen, aber es legt wirklich die Unterschiede zwischen den verschiedenen JS-Designpatterns dar. Es hat mir sehr geholfen: addyosmani.com/resources/essentialjsdesignpatterns/book

29voto

iaforek Punkte 2344

Wenn Sie node.JS verwenden, können Sie von node.JS Caching-Mechanismus profitieren und Ihr Singleton wird so einfach sein:

class Singleton {
    constructor() {
        this.message = 'Ich bin eine Instanz';
    }
}
module.exports = new Singleton();

Bitte beachten Sie, dass wir nicht die Klasse Singleton exportieren, sondern Instanz Singleton().

Node.JS wird das gleiche Objekt jedes Mal zwischenspeichern und wiederverwenden, wenn es benötigt wird.

Weitere Details finden Sie hier: Node.JS und Singleton-Muster

0 Stimmen

Ich sehe nichts im OP bezüglich node.js.

2 Stimmen

Ich sehe auch nichts explizit über node.js, noch dass es in Vanilla JS sein muss. Daher habe ich klar hinzugefügt, dass dies für JS und node ist. Sie können es wirklich einfacher und sauberer machen, WENN Sie Node.JS verwenden! Außerdem haben, basierend auf den Upvotes, mehr Leute das hilfreich gefunden als nicht.

1 Stimmen

@iaforek Vielen Dank. Dies ist bisher der beste Weg für meinen Anwendungsfall. Sehr geschätzt.

19voto

Daniel Punkte 327

Das folgende funktioniert in Node.js Version 6:

class Foo {
  constructor(msg) {

    if (Foo.singleton) {
      return Foo.singleton;
    }

    this.msg = msg;
    Foo.singleton = this;
    return Foo.singleton;
  }
}

Wir testen:

const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }

12voto

Wolfgang Fahl Punkte 13424

Das einfachste/Sauberste für mich bedeutet auch einfach zu verstehen und keine Schnörkel, wie sie in der Java-Version der Diskussion viel diskutiert werden:

Was ist ein effizienter Weg, um ein Singleton-Muster in Java zu implementieren?

Die Antwort, die meiner Meinung nach am einfachsten/saubersten passt, ist:

Jonathans Antwort zu Was ist ein effizienter Weg, um ein Singleton-Muster in Java zu implementieren?

Und es kann nur teilweise in JavaScript übersetzt werden. Einige der Unterschiede in JavaScript sind:

  • Konstruktoren können nicht privat sein
  • Klassen können keine deklarierten Felder haben

Aber mit der neuesten ECMA-Syntax ist es möglich, nahe dran zu kommen mit:

Singleton-Muster als JavaScript-Klassenbeispiel

 class Singleton {

  constructor(field1,field2) {
    this.field1=field1;
    this.field2=field2;
    Singleton.instance=this;
  }

  static getInstance() {
    if (!Singleton.instance) {
      Singleton.instance=new Singleton('DefaultField1','DefaultField2');
    }
    return Singleton.instance;
  }
}

Beispiel Verwendung

console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);

Beispiel Ergebnis

DefaultField1
DefaultField2

0 Stimmen

Ich habe gut erhaltene Antworten überprüft, aber ich denke, dass diese hier unterbeachtet ist. +1 übrigens

0 Stimmen

Ich bin neu in JavaScript und komme von Java, und muss fragen, wie verhindert wird, dass man new Singleton() ausführt und dadurch das Singleton-Muster unterbrochen wird?

0 Stimmen

@Erik - es funktioniert nicht, es ist nur eine Konvention, dass du getInstance nennst

12voto

Supradeep Punkte 141

Wenn Sie Klassen verwenden möchten:

class Singleton {
  constructor(name, age) {
    this.name = name;
    this.age = age;
    if(this.constructor.instance)
      return this.constructor.instance;
    this.constructor.instance = this;
  }
}
let x = new Singleton('s', 1);
let y = new Singleton('k', 2);

Der Output für das obige Beispiel wird sein:

console.log(x.name, x.age, y.name, y.age) // s 1 s 1

Eine andere Möglichkeit, Singleton mit einer Funktion zu schreiben

function AnotherSingleton (name,age) {
  this.name = name;
  this.age = age;
  if(this.constructor.instance)
    return this.constructor.instance;
  this.constructor.instance = this;
}

let a = new AnotherSingleton('s', 1);
let b = new AnotherSingleton('k', 2);

Der Output für das obige Beispiel wird sein:

console.log(a.name, a.age, b.name, b.age) // s 1 s 1

7voto

Khamidulla Punkte 2899

Ich habe dieses Beispiel aus dem *JavaScript Patterns Erstellen Sie bessere Anwendungen mit Codierungs- und Entwurfsmustern Buch (von Stoyan Stefanov). Falls Sie eine einfache Implementierungsklasse wie ein Singleton-Objekt benötigen, können Sie eine sofortige Funktion wie folgt verwenden:

var Klassenname;

(function() {
    var instanz;
    Klassenname = function Klassenname() {
        // Wenn die private Instanzvariable bereits initialisiert ist, geben Sie eine Referenz zurück
        if(instanz) {
            return instanz;
        }
        // Wenn die Instanz nicht erstellt wurde, speichern Sie einen Verweis auf die ursprüngliche Referenz
        // zur privaten Instanzvariable.
        instanz = this;

        // Alle Konstruktorinitialisierungen werden hier erfolgen
        // z.B.:
        this.eineEigenschaft = 0;
        this.eineMethode = function() {
            // Hier eine Aktion
        };
    };
}());

Und Sie können dieses Beispiel mit folgendem Testfall überprüfen:

// Erweiterung der definierten Klasse wie ein Singleton-Objekt unter Verwendung der neuen Prototyp-Eigenschaft
Klassenname.prototype.nichts = true;
var obj_1 = new Klassenname();

// Erweiterung der definierten Klasse wie ein Singleton-Objekt unter Verwendung der neuen Prototyp-Eigenschaft
Klassenname.prototype.alles = true;
var obj_2 = new Klassenname();

// Test macht deutlich, dass diese beiden Objekte auf dieselbe Instanz zeigen
console.log(obj_1 === obj_2); // Ergebnis ist true und es zeigt auf dasselbe Instanzobjekt

// Alle Prototyp-Eigenschaften funktionieren
// egal wann sie definiert wurden
console.log(obj_1.nichts && obj_1.alles
            && obj_2.nichts && obj_2.alles); // Ergebnis true

// Werte von Eigenschaften, die im Konstruktor definiert sind
console.log(obj_1.eineEigenschaft); // Ausgabe 0
console.log(obj_2.eineEigenschaft); // Ausgabe 0

// Änderung des Eigenschaftswerts
obj_1.eineEigenschaft = 1;

console.log(obj_1.eineEigenschaft); // Ausgabe 1
console.log(obj_2.eineEigenschaft); // Ausgabe 1

console.log(obj_1.constructor === Klassenname); // Ausgabe true

Dieser Ansatz besteht alle Testfälle, während eine private statische Implementierung scheitert, wenn eine Prototyperweiterung verwendet wird (es kann behoben werden, aber es wird nicht einfach sein) und eine öffentliche statische Implementierung weniger ratsam ist, da eine Instanz öffentlich zugänglich ist.

jsFiddly Demo.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X