2015-06-02 5 views
7

Ich hatte einen älteren JS-Code, der eine riesige verschachtelte Objektstruktur mit [] erstellt. Der Code geht etwas wie diesesNimmt {} weniger Speicherplatz als [] für verschachtelte Objekte in Javascript auf?

var data = []; 
data ["first"] = []; 
data ["first"]["second"] = []; 
data ["first"]["second2"] = "hello"; 

Es geht um mehr als 250 KB von Javascript, die ziemlich groß ist. Wenn ich versuche, es mit requirys zu umbrechen, um es in ein anderes requestejs-Modul zu laden, wird der Fehler "Nicht genügend Arbeitsspeicher" ausgegeben.

Der Fehler verschwindet, wenn ich {} verwende, wo ich [] verwendet habe.

Ich habe am Wochenende einige Hausaufgaben auf [] vs. {} gemacht und die Ursache scheint zu sein, dass die Verwendung assoziierter Arrays als verschachtelte Wörterbücher in Javascript undicht sein kann, da Array ein JS-Objekt erweitert und möglicherweise mehr Update-Sachen haben wenn neue Objekte hinzugefügt werden. Aber erklärt es das Speicherverbrauchsproblem? Oder hängt es damit zusammen, wie Requirejs das Objekt eines Moduls analysiert?

Ich habe nicht genug Kenntnisse über JS Speicher Instrumentierung und Vergleiche zwischen der Verwendung von {} oder [] in Browser-Engines, so dass es schwierig ist, Schlussfolgerungen zu erzielen. Jeder Hinweis oder Vorschlag, wie man {} vs. [] instrumentiert, wäre willkommen.

Update: Ich versuchte gestern einige sizeOf() über Knoten. Früher habe ich alle der bestehenden: "js-sizeof", "Objekt-sizeof", "sizeof"

Code:

var sizeof = require('object-sizeof'); 


var obj = []; 
obj['ball'] = 'hello'; 
obj['air'] = 'hello'; 
obj['ball']['fire'] = 'world'; 
obj['ball']['ice'] = []; 
console.log(sizeof(obj)); 

var obj2 = {}; 
obj2['ball'] = 'hello'; 
obj2['air'] = 'hello'; 
obj2['ball']['fire'] = 'world'; 
obj2['ball']['ice'] = []; 
console.log(sizeof(obj2)); 

Die Ergebnisse ist

[]: 34 {} : 34

Die sizeOf ist eigentlich die gleiche., Aber vielleicht etwas anderes passiert mit [], die Speicherproblem auslösen könnte. Ich bin mir nicht sicher, ob es die Anforderungen sind, die es analysieren, die es oder einen V8-Optimierungspfad auslösen. Ich glaube nicht, dass die Lint-Werkzeuge sogar gegen diese Praxis sprechen, daher ist es eher zweideutig, welcher Weg der "richtige" Weg in der Praxis ist.

+1

Sie sind alle Objekte, aber wenn, ''} wird mehr konsumieren, da Sie die Zeichenfolge des Schlüssels anstelle nur eines ganzzahligen Indexes speichern müssen. –

+2

@MarcB: Falsch. Das hängt davon ab, welche Tasten Sie verwenden, nicht ob es ein Array ist. – SLaks

+2

[Array für diesen Zweck ist einfach falsch] (http://andrewdupont.net/2006/05/18/jacascript-associative-arrays-consided-harmful/). Es spielt keine Rolle, dass sie auch mehr Speicher verbrauchen. – Bergi

Antwort

5

In JavaScript gibt es kein "assoziiertes Array". [ 1, 2, 3 ] ist Array-Literalsyntax; Es initialisiert ein Array. { foo: "bar" } ist Objektliteralsyntax; Es initialisiert ein Objekt. Eine Marotte von JavaScript ist jedoch, dass Arrays zufällig auch Objekte sein, weshalb dieser Code „funktioniert“:

var data = []; 
data["first"] = []; 
data["first"]["second"] = []; 

... aber Sie sollten es nicht tun, weil es ein nicht machen Sinn. Sie initialisieren ein leeres Array ([]), aber Sie verwenden es nicht wie ein Array - Sie verwenden es wie ein Objekt. Wenn Sie anstelle von ganzzahligen Schlüsseln (data[0]) Eigenschaftsnamen (data["first"], was data.first entspricht) verwenden, dann möchten Sie ein Objekt verwenden. Es gibt kein Szenario, in dem Sie ein Array initialisieren sollten, wenn Sie es wie ein Objekt verwenden möchten.

Als Faustregel gilt: Wenn Sie für jedes Element einen Namen benötigen oder schnell auf einen Namen zugreifen können, verwenden Sie ein Objekt ({}) und verwenden Sie Strings für Schlüssel. Wenn Sie in der Lage sein müssen, die Elemente der Reihe nach zu durchlaufen, verwenden Sie ein Array mit Ganzzahlen für Schlüssel.

Ich kenne nicht die genaue Ursache für Ihren Speichermangel - vor allem nicht ohne Ihren tatsächlichen Code zu sehen - aber es ist definitiv der Fall, dass Sie ein Objekt ({}), kein Array ([]), wenn Sie keine Integer-Schlüssel verwenden.JavaScript-Engines optimieren alles, was sie können, und Arrays und Objekte sind keine Ausnahme. Es ist daher nicht verwunderlich, dass bei der Verwendung eines Arrays auf eine Weise, die von der Engine nicht erwartet wird, Performance- oder Speicherprobleme auftreten können.

P.S. Als eine Frage des Stils, betrachtet Eigenschaft Notation (oder „Punktnotation“, dh foo.bar) anstelle von Index-Notation (dh foo["bar"]), wenn mit Objekten zu tun:

var data = {}; 
data.first = {}; 
data.first.second = {}; 
data.first.second2 = "hello"; 

Dies genau den Code entspricht Sie auf dem Laufenden, aber es ist einfacher zu lesen und hilft Ihnen vielleicht dabei, sich daran zu erinnern, dass Objekte und Arrays unterschiedliche Anwendungen haben. Sie könnten auch ausdrücken gerade dies als ein einzelnes Objekt wörtlichen:

var data = { 
    first: { 
    second: {}, 
    second2: "hello" 
    } 
}; 

Dies auch genau entspricht und hilft Ihnen, die „Struktur“ des Objekts sehen (solange Sie Einbuchtung diszipliniert sind).

Die meisten JavaScript-Stil-Anleitungen sagen, dass Sie immer "Punktnotation" verwenden sollten, es sei denn, Sie haben Schlüssel, die einen Syntaxfehler verursachen würden. Zum Beispiel, wenn Sie eine Eigenschaft namens "foo/bar" haben, können Sie natürlich nicht tun:

var obj.foo/bar = 1; 

... weil es ein Syntaxfehler ist. Also müssen Sie das tun:

var obj["foo/bar"] = 1; 

... was absolut gültig ist. Diese Fälle neigen dazu, die Ausnahme zu sein, so würde ich ermutigen, Punktnotation immer zu verwenden, wenn Sie verwenden tiefgestellte Notation verwenden müssen.

+0

Mein Verständnis ist, dass ary = [1,2,3] ein Objekt initialisiert {1: 1, 2: 2, 3: 3}, weshalb ary [10000000] = 123 funktioniert, ohne Ihre Maschine zu zerstören. Alle Arrays sind Objekte, und alle Objekte funktionieren wie assoziierte Arrays (Listen (LISP)), aber sie haben ein paar zusätzliche Methoden, mit denen Sie sie sinnvoll initialisieren können, die Länge usw. erhalten. Das obige Beispiel wäre besser in JSON geschrieben, aber ich derzeit nicht einverstanden mit Ihren Gründen warum. Kannst du mich anders überzeugen? – superluminary

+0

Ja, genau das habe ich in meinem ersten Absatz geschrieben. Und ich habe keinen Anreiz, Sie zu überzeugen, also müssen Sie mit meiner Antwort unzufrieden sein. –

+1

Ich wollte nicht unhöflich sein, ich glaubte nur, dass ich mich geirrt habe. – superluminary