[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/WeakMap [Back]  [Original]

WeakMap - JavaScript | MDN

Dieser Inhalt wurde automatisch aus dem Englischen bersetzt, und kann Fehler enthalten. Erfahre mehr ber dieses Experiment.

View in English Always switch to English

WeakMap

Baseline
Weitgehend verfgbar
*

Diese Funktion ist gut etabliert und funktioniert auf vielen Gerten und in vielen Browserversionen. Sie ist seit Juli 2015 browserbergreifend verfgbar.

* Einige Teile dieser Funktion werden mglicherweise unterschiedlich gut untersttzt.

Ein WeakMap ist eine Sammlung von Schlssel/Wert-Paaren, deren Schlssel Objekte oder nicht registrierte Symbole sein mssen, mit Werten eines beliebigen JavaScript-Typs, und die keine starken Referenzen auf ihre Schlssel erstellt. Das heit, die Prsenz eines Objekts als Schlssel in einer WeakMap verhindert nicht, dass das Objekt dem Garbage-Collector zum Opfer fllt. Sobald ein Objekt, das als Schlssel verwendet wird, gesammelt wurde, werden seine entsprechenden Werte in jeder WeakMap ebenfalls fr die Mllsammlung in Frage kommen solange sie nicht anderswo stark referenziert werden. Der einzige primitive Typ, der als WeakMap-Schlssel verwendet werden kann, ist das Symbol genauer gesagt nicht registrierte Symbole weil nicht registrierte Symbole garantiert einzigartig sind und nicht neu erstellt werden knnen.

WeakMap ermglicht es, Daten mit Objekten zu assoziieren, ohne zu verhindern, dass die Schlsselobjekte gesammelt werden, selbst wenn die Werte die Schlssel referenzieren. Allerdings erlaubt WeakMap nicht die Beobachtung der Existenz seiner Schlssel, weshalb sie keine Enumeration zulsst; wenn eine WeakMap eine Methode bereitstellen wrde, um eine Liste ihrer Schlssel zu erhalten, wrde die Liste vom Zustand der Mllsammlung abhngen, was zu Nicht-Determinismus fhren wrde. Wenn Sie eine Liste von Schlsseln haben mchten, sollten Sie eine Map anstelle einer WeakMap verwenden.

Sie knnen mehr ber WeakMap im Abschnitt WeakMap-Objekt des Leitfadens zu Schlssel-Sammlungen erfahren.

In diesem Artikel

Beschreibung

Schlssel von WeakMaps mssen dem Garbage-Collector ausgeliefert werden knnen. Die meisten primitiven Datentypen knnen willkrlich erstellt werden und haben keine Lebensdauer, daher knnen sie nicht als Schlssel verwendet werden. Objekte und nicht registrierte Symbole knnen als Schlssel verwendet werden, da sie dem Garbage-Collector ausgeliefert werden knnen.

Schlsseligleichheit

Wie bei regulren Map basiert die Wertegleichheit auf dem SameValueZero-Algorithmus, der dem ===-Operator entspricht, da WeakMap nur Objekt- und Symbolschlssel enthalten kann. Das bedeutet, dass fr Objektschlssel die Gleichheit auf der Objektidentitt basiert. Sie werden durch Referenz und nicht durch Wert verglichen.

Warum WeakMap?

Eine Map-API knnte in JavaScript mit zwei Arrays (eines fr Schlssel, eines fr Werte) implementiert werden, die von den vier API-Methoden gemeinsam genutzt werden. Das Setzen von Elementen in dieser Map wrde bedeuten, gleichzeitig einen Schlssel und einen Wert an das Ende jedes der Arrays zu schieben. Dadurch wrden die Indizes des Schlssels und des Werts mit beiden Arrays korrespondieren. Das Abrufen von Werten aus der Map wrde das Durchlaufen aller Schlssel erfordern, um eine bereinstimmung zu finden, und dann den Index dieser bereinstimmung verwenden, um den entsprechenden Wert aus dem Werte-Array abzurufen.

Eine solche Implementierung hat zwei Hauptnachteile:

  1. Der erste ist ein O(n)-Setzen und Suchen (n ist die Anzahl der Schlssel in der Map), da beide Operationen die Liste der Schlssel durchlaufen mssen, um einen passenden Wert zu finden.
  2. Der zweite Nachteil ist ein Speicherleck, da die Arrays sicherstellen, dass Referenzen auf jeden Schlssel und jeden Wert unbegrenzt erhalten bleiben. Diese Referenzen verhindern, dass die Schlssel dem Garbage-Collector zum Opfer fallen, selbst wenn es keine anderen Referenzen zum Objekt gibt. Dies wrde auch verhindern, dass die entsprechenden Werte dem Garbage-Collector zum Opfer fallen.

Im Gegensatz dazu bezieht sich in einer WeakMap ein Schlsselobjekt stark auf seinen Inhalt, solange der Schlssel nicht dem Garbage-Collector zum Opfer gefallen ist, aber danach schwach darauf. Daher:

  • verhindert eine WeakMap nicht die Mllsammlung, die letztendlich Referenzen zum Schlsselobjekt entfernt
  • ermglicht eine WeakMap die Mllsammlung jeglicher Werte, wenn ihre Schlsselobjekte nicht von einem anderen Ort als einer WeakMap referenziert werden

Eine WeakMap kann ein besonders ntzliches Konstrukt sein, wenn man Schlssel mit Informationen verknpft, die nur dann wertvoll sind, wenn der Schlssel nicht dem Garbage-Collector zum Opfer gefallen ist.

Aber da eine WeakMap nicht die Beobachtung der Existenz ihrer Schlssel erlaubt, sind ihre Schlssel nicht aufzhlbar. Es gibt keine Methode, um eine Liste der Schlssel zu erhalten. Wenn es eine gbe, wrde die Liste vom Zustand der Mllsammlung abhngen, was zu Nicht-Determinismus fhren wrde. Wenn Sie eine Liste von Schlsseln haben mchten, sollten Sie eine Map verwenden.

Konstruktor

WeakMap()

Erstellt ein neues WeakMap-Objekt.

Instanzeigenschaften

Diese Eigenschaften sind auf WeakMap.prototype definiert und werden von allen WeakMap-Instanzen geteilt.

WeakMap.prototype.constructor

Die Konstruktorfunktion, die das Instanzobjekt erstellt hat. Fr WeakMap-Instanzen ist der anfngliche Wert der WeakMap-Konstruktor.

WeakMap.prototype[Symbol.toStringTag]

Der anfngliche Wert der [Symbol.toStringTag]-Eigenschaft ist der String "WeakMap". Diese Eigenschaft wird in Object.prototype.toString() verwendet.

Instanzmethoden

WeakMap.prototype.delete()

Entfernt den durch den Schlssel angegebenen Eintrag aus dieser WeakMap.

WeakMap.prototype.get()

Gibt den Wert zurck, der dem Schlssel in dieser WeakMap entspricht, oder undefined, wenn keiner vorhanden ist.

WeakMap.prototype.getOrInsert()

Gibt den Wert zurck, der dem angegebenen Schlssel in dieser WeakMap entspricht. Wenn der Schlssel nicht vorhanden ist, wird ein neuer Eintrag mit dem Schlssel und einem angegebenen Standardwert eingefgt und der eingefgte Wert zurckgegeben.

WeakMap.prototype.getOrInsertComputed()

Gibt den Wert zurck, der dem angegebenen Schlssel in dieser WeakMap entspricht. Wenn der Schlssel nicht vorhanden ist, wird ein neuer Eintrag mit dem Schlssel und einem Standardwert eingefgt, der aus einem gegebenen Rckruf berechnet wird, und der eingefgte Wert wird zurckgegeben.

WeakMap.prototype.has()

Gibt einen booleschen Wert zurck, der angibt, ob ein Eintrag mit dem angegebenen Schlssel in dieser WeakMap existiert oder nicht.

WeakMap.prototype.set()

Fgt einen neuen Eintrag mit einem angegebenen Schlssel und Wert zu dieser WeakMap hinzu oder aktualisiert einen bestehenden Eintrag, wenn der Schlssel bereits existiert.

Beispiele

Verwendung von WeakMap

js
const wm1 = new WeakMap();
const wm2 = new WeakMap();
const wm3 = new WeakMap();
const o1 = {};
const o2 = () => {};
const o3 = window;

wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // a value can be anything, including an object or a function
wm2.set(o2, undefined);
wm2.set(wm1, wm2); // keys and values can be any objects. Even WeakMaps!

wm1.get(o2); // "azerty"
wm2.get(o2); // undefined, because that is the set value
wm2.get(o3); // undefined, because there is no key for o3 on wm2

wm1.has(o2); // true
wm2.has(o2); // true (even if the value itself is 'undefined')
wm2.has(o3); // false

wm3.set(o1, 37);
wm3.get(o1); // 37

wm1.has(o1); // true
wm1.delete(o1);
wm1.has(o1); // false

Implementierung einer WeakMap-hnlichen Klasse mit einer .clear() Methode

js
class ClearableWeakMap {
  #wm;
  constructor(init) {
    this.#wm = new WeakMap(init);
  }
  clear() {
    this.#wm = new WeakMap();
  }
  delete(k) {
    return this.#wm.delete(k);
  }
  get(k) {
    return this.#wm.get(k);
  }
  has(k) {
    return this.#wm.has(k);
  }
  set(k, v) {
    this.#wm.set(k, v);
    return this;
  }
}

Emulieren privater Mitglieder

Entwickler knnen eine WeakMap verwenden, um private Daten mit einem Objekt zu verknpfen, mit den folgenden Vorteilen:

  • Im Vergleich zu einer Map hlt eine WeakMap keine starken Referenzen auf das Objekt, das als Schlssel verwendet wird, sodass die Metadaten die gleiche Lebensdauer wie das Objekt selbst teilen, was Speicherlecks vermeidet.
  • Im Vergleich zur Verwendung von nicht aufzhlbaren und/oder Symbol-Eigenschaften ist eine WeakMap extern zum Objekt und es gibt keine Mglichkeit fr Benutzer-Code, die Metadaten durch reflektive Methoden wie Object.getOwnPropertySymbols abzurufen.
  • Im Vergleich zu einer Closure kann dieselbe WeakMap fr alle aus einem Konstruktor erstellten Instanzen wiederverwendet werden, was speichereffizienter ist, und erlaubt es verschiedenen Instanzen der gleichen Klasse, die privaten Mitglieder voneinander zu lesen.
js
let Thing;

{
  const privateScope = new WeakMap();
  let counter = 0;

  Thing = function () {
    this.someProperty = "foo";

    privateScope.set(this, {
      hidden: ++counter,
    });
  };

  Thing.prototype.showPublic = function () {
    return this.someProperty;
  };

  Thing.prototype.showPrivate = function () {
    return privateScope.get(this).hidden;
  };
}

console.log(typeof privateScope);
// "undefined"

const thing = new Thing();

console.log(thing);
// Thing {someProperty: "foo"}

thing.showPublic();
// "foo"

thing.showPrivate();
// 1

Dies kommt ungefhr dem folgenden gleich, unter Verwendung von privaten Feldern:

js
class Thing {
  static #counter = 0;
  #hidden;
  constructor() {
    this.someProperty = "foo";
    this.#hidden = ++Thing.#counter;
  }
  showPublic() {
    return this.someProperty;
  }
  showPrivate() {
    return this.#hidden;
  }
}

const thing = new Thing();

console.log(thing);
// Thing {someProperty: "foo"}

thing.showPublic();
// "foo"

thing.showPrivate();
// 1

Verknpfen von Metadaten

Eine WeakMap kann verwendet werden, um Metadaten mit einem Objekt zu verknpfen, ohne die Lebensdauer des Objekts selbst zu beeinflussen. Dies ist dem Beispiel der privaten Mitglieder sehr hnlich, da private Mitglieder ebenfalls als externe Metadaten modelliert sind, die nicht an der prototypischen Vererbung teilnehmen.

Dieser Anwendungsfall kann auf bereits erstellte Objekte ausgeweitet werden. Zum Beispiel mchten wir im Web mglicherweise zustzliche Daten mit einem DOM-Element verknpfen, auf das das DOM-Element spter zugreifen kann. Ein gngiger Ansatz ist es, die Daten als Eigenschaft hinzuzufgen:

js
const buttons = document.querySelectorAll(".button");
buttons.forEach((button) => {
  button.clicked = false;
  button.addEventListener("click", () => {
    button.clicked = true;
    const currentButtons = [...document.querySelectorAll(".button")];
    if (currentButtons.every((button) => button.clicked)) {
      console.log("All buttons have been clicked!");
    }
  });
});

Dieser Ansatz funktioniert, hat aber ein paar Stolpersteine:

  • Die clicked-Eigenschaft ist aufzhlbar, sodass sie in Object.keys(button), for...in-Schleifen usw. angezeigt wird. Dies kann durch die Verwendung von Object.defineProperty() gemildert werden, aber das macht den Code ausfhrlicher.
  • Die clicked-Eigenschaft ist eine normale String-Eigenschaft, sodass sie von anderem Code zugegriffen und berschrieben werden kann. Dies kann durch die Verwendung eines Symbol-Schlssels gemildert werden, aber der Schlssel wre weiterhin ber Object.getOwnPropertySymbols() zugnglich.

Die Verwendung einer WeakMap behebt diese Probleme:

js
const buttons = document.querySelectorAll(".button");
const clicked = new WeakMap();
buttons.forEach((button) => {
  clicked.set(button, false);
  button.addEventListener("click", () => {
    clicked.set(button, true);
    const currentButtons = [...document.querySelectorAll(".button")];
    if (currentButtons.every((button) => clicked.get(button))) {
      console.log("All buttons have been clicked!");
    }
  });
});

Hier wei nur der Code, der Zugriff auf clicked hat, den Zustand dieser State und externer Code kann den Zustand nicht modifizieren. Zudem werden, wenn eines der Schaltflchen-Elemente aus dem DOM entfernt wird, die zugehrigen Metadaten automatisch dem Garbage-Collector zum Opfer fallen.

Caching

Sie knnen Objekte, die an eine Funktion bergeben werden, mit dem Ergebnis der Funktion verknpfen, sodass wenn dasselbe Objekt erneut bergeben wird, das zwischengespeicherte Ergebnis zurckgegeben werden kann, ohne die Funktion erneut auszufhren. Dies ist ntzlich, wenn die Funktion rein ist (d.h. sie verndert keine auenstehenden Objekte oder verursacht andere beobachtbare Seiteneffekte).

js
const cache = new WeakMap();
function handleObjectValues(obj) {
  if (cache.has(obj)) {
    return cache.get(obj);
  }
  const result = Object.values(obj).map(heavyComputation);
  cache.set(obj, result);
  return result;
}

Dies funktioniert nur, wenn die Eingabe Ihrer Funktion ein Objekt ist. Selbst wenn die Eingabe nie erneut bergeben wird, bleibt das Ergebnis fr immer im Cache, solange der Schlssel (Eingabe) existiert. Eine effektivere Methode ist die Verwendung einer Map gepaart mit WeakRef-Objekten, die es ermglichen, jeden Eingabewert mit seinem entsprechenden (potenziell groen) Berechnungsergebnis zu verknpfen. Weitere Details finden Sie im Beispiel WeakRefs und FinalizationRegistry.

Spezifikationen

Spezifikation
ECMAScript 2027 LanguageSpecification
# sec-weakmap-objects

Browser-Kompatibilitt

Siehe auch


Web Proxy Viewer  |  New URL  |  Original Page