6 Stimmen

Warum stellt JQuery seine UUID-Funktionalität nicht zur Verfügung?

Unter der Haube verwendet JQuery eine Karte von "UUIDs" (nur ein Zähler, den es als jQuery.uuid ), um die bekannten Speicherleck-Probleme zu umgehen, die Browser haben, wenn Sie eine Eigenschaft an ein Tag im DOM von Javascript anhängen. Anstelle dessen verwendet JQuery die $.data(tag, name, value) um Daten in einer Karte zu speichern, die anhand der uuid verschlüsselt ist (ein Schlüssel, der durch Überprüfung der tag[jQuery.expando] ).

Während $.data() sehr nützlich ist, gibt es Fälle, in denen Sie Daten zu Tags zuordnen möchten, ohne diese Daten in einen globalen Bereich zu packen - Sie möchten einen eigenen kleineren Bereich von Daten, den Sie zum Beispiel auf seine Länge prüfen oder in einer Schleife durchlaufen können.

Nehmen wir als Beispiel an, Sie haben Symbole, die beim Anklicken einen von 4 Zuständen durchlaufen. Wenn sich ein Symbol im Zustand 2 befindet, möchten Sie es zu einem Array von Symbolen im Zustand 2 hinzufügen. Der naheliegendste Weg, dies zu tun, ist das Hinzufügen des Tags zu einem Array; dies würde jedoch zu einem Speicherleck führen. Sie könnten aufrufen $.data() auf das Kontrollkästchen, aber das bringt nicht ganz das, was Sie erreichen wollen - Sie müssten alle Kontrollkästchen in einer Schleife überprüfen $.data() um herauszufinden, welche auf der Liste stehen und welche nicht.

Sie müssen eine Abstraktion der Tags in einem Array speichern, und das sind die UUIDs von jQuery. Sie könnten Ihre eigene UUID-Funktionalität schreiben, aber idealerweise nutzen Sie einfach die UUID-Funktionalität, die bereits in JQuery integriert ist, sowohl aus Gründen der Code-Größe als auch der Qualität. Sie könnten JQuery auffordern, eine UUID implizit an das Tag anzuhängen, indem Sie $.data(tag, 'irrelevant', 1) und prüfen Sie dann tag[jQuery.expando] um seine UUID zu erhalten, und schließlich verwenden, dass in der Liste... aber das ist ein bisschen ein Hack. Wirklich ideal wäre es, wenn in der öffentlichen API Folgendes offengelegt würde:

$.getUuid(tag) : Prüft, ob eine UUID vorhanden ist, und erstellt sie, falls keine vorhanden ist - idealerweise wird die Methode aus der $.data() und erstellt oder holt die uuid für das übergebene Tag.

Also, gibt es einen Grund, dies ist nicht in seine eigene Methode in jQuery ausgeklammert? Ist dies in irgendeiner Weise schädlich? War es einfach nie etwas, das nützlich erschien?

Ich sollte anmerken, dass ich es in der Version von jQuery, die wir verwenden, tatsächlich berücksichtigt habe, und es ist sehr hilfreich. Aber vielleicht gibt es ein zugrundeliegendes Risiko, das ich in meiner Verwendung nicht treffe. Ich bin auch bewusst, ein Plugin, das Art-of erreicht dies, aber es ist ein bisschen gebrochen - und mit 2 codepaths, die gleiche UUID-Funktionalität durchführen ist sowohl ein bisschen verschwenderisch und ein bisschen spröde.

4voto

jfriend00 Punkte 632952

Ich denke, die offensichtliche Antwort hier ist, dass jQuery ihre uuid für den internen Gebrauch gebaut und hat nicht gesehen, einen großen Grund oder große Nachfrage zu stören es öffentlich konsumierbar zu machen. Das bedeutet nicht, dass es keine Gründe gibt, sondern nur, dass sie nicht wichtig genug erschienen, um sie ganz oben auf die Liste der Dinge zu setzen, an denen man arbeiten muss.

Monotomisch ansteigende Zähler, die als eindeutige IDs verwendet werden können, sind ziemlich trivial zu implementieren und ich habe sie schon oft verwendet. Ich hatte nicht das Gefühl, dass ich dafür die Unterstützung der Klassenbibliothek benötigte.

Ich denke, Ihre Angst vor Speicherlecks, weil Sie Objektreferenzen herum halten, ist ein bisschen übertrieben. Erstens ist es nur dann ein Speicherleck, wenn man das Objekt loswird und vergisst, einen Verweis darauf loszuwerden. Das ist nur eine allgemeine Regel in Garbage-Collector-Sprachen, die besagt, dass man "wissen" muss, wo man Verweise auf Objekte aufbewahrt, die man möglicherweise loswerden will, und diese Verweise aufräumen muss, wenn man beabsichtigt, das Objekt freizugeben.

Zweitens ist es nur dann ein bedeutendes Speicherleck, wenn Sie dieselbe Sache viele Male pro Seite tun oder wenn das Objekt sehr, sehr groß ist. Sie werden alle aufgeräumt, wenn man zur nächsten Seite wechselt. Es ist also nicht so, dass sich das für immer anhäuft, es sei denn, man verlässt die Browserseite nie und macht immer wieder dasselbe, was entfernte Objekte, aber nicht entfernte Referenzen einschließt.

Drittens versucht der .data()-Mechanismus von jQuery, vieles davon für Sie zu lösen, wenn Sie DOM-Objekte verwenden.

Viertens: In Ihrem konstruierten Beispiel führt dies nicht zu einem Speicherleck, es sei denn, Sie bereinigen Ihr Array von Symbolen im Zustand 2 nicht, wenn es nicht mehr gültig ist oder nicht mehr verwendet wird. Wenn Sie es bereinigen, dann gibt es kein Problem mit der Speicherung einer direkten DOM-Referenz in diesem Array. Wenn Sie das Array nicht bereinigen, dann ist sogar das Array selbst ein Speicherleck, auch wenn es abstrakte uuids anstelle von DOM-Referenzen enthält. Die Verwendung von abstrakten Referenzen ist in den meisten Fällen einfach viel mehr Arbeit als nötig.

Auch hier gilt: Selbst wenn Sie es zu einem Leck bringen, sind die Lecks nur wichtig, wenn die Seite eine lange Lebensdauer hat und Sie wiederholt Objekte erstellen und freigeben, aber nicht alle Verweise auf sie löschen, so dass sich die Verweise im Laufe der Zeit ansammeln, und zwar so sehr, dass das von ihnen verursachte Speicherleck von Bedeutung ist. Ich behalte Referenzen auf DOM-Objekte in JS-Variablen die ganze Zeit. Ich achte nur darauf, dass ich sie lösche, wenn ich sie nicht mehr brauche, damit ich weiß, dass das DOM-Objekt irgendwann wieder freigegeben werden kann.

0voto

Chris Moschini Punkte 34996

Dies wurde dem jQuery-Team vorgelegt und abgelehnt.

Sie können jedoch eine Liste von Tags pflegen, die die Garbage Collection an jQuery delegiert, wie folgt:

http://jsfiddle.net/b9chris/Un2mH/

Der wesentliche Code ist:

sets[oldIndex] = sets[oldIndex].not(this);
sets[index] = sets[index].add(this);

Dies führt zwar zu einer separaten Speicherbelastung, aber diese Methoden fügen nicht nur ein Tag zu einem Array hinzu, sondern führen auch einen Stapel der vorherigen Zustände dieser Sammlung (.pushStack() wird intern aufgerufen). Wenn die Seite sehr langlebig ist und es viele Benutzeraktionen gibt, werden die Sammlungen unendlich wachsen. Um dies zu verhindern, kann man die Objekte so hacken, dass sie den Stack löschen:

sets[oldIndex] = sets[oldIndex].not(this);
sets[oldIndex].prevObject = null;
sets[index] = sets[index].add(this);
sets[index].prevObject = null;

Eine Verschwendung von einigen CPU-Zyklen, aber sauber genug.

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