2012-05-01 15 views
5

In JavaScript können Sie Objekte mit einer Art von extend Funktion erstellen.So vermeiden Sie Namenskonflikte beim Erstellen von Objekten

Zum Beispiel könnte ich eine observable Klasse, die eine Reihe von öffentlichen Methoden aussetzt (get, push, set, increment, get usw.)

die beobachtbare geschieht auch in diesem Fall auch ein EventEmitter so es zu sein legt einen weiteren Satz von öffentlichen Methoden (emit, on, removeListener usw.)

beiden Klassen interne Unterstreichungsvoran Eigenschaften aufweisen, die den Zustand speichern. Der eventetitter verwendet _events, um Ereignishandler zu speichern, und die beobachtbaren Verwendungen _state und _id speichern den Status und die ID.

Nun, wenn ich erstelle ein Modell wie Objekt-Komposition mit so

var Model = extend({}, Observable, { 
    constructor: function() { 
     // Oops, I was supposed to know Observable uses the _state name already 
     this._state = { ... } 
    }, 
    someMethod: function() { ... } 
}) 

Dies führt zu einem Problem, weil Observable bereits verwendet die _state interne Eigenschaft und es gibt jetzt einen Namenskonflikt.

Ich würde es hässlich halten, einfach zu "wissen", welche Objekte sich darauf verlassen, welche internen Eigenschaften für das Mixin sicher funktionieren.

Wie vermeiden Sie das Mischen in zwei Objekten, die den gleichen internen Eigenschaftsnamen verwenden?

Im Idealfall würde dies mit den privaten ES6-Namen gelöst werden, aber das können wir noch nicht tun, und wir können sie nicht ohne Leistungsverlust emulieren. Sofern Sie keine ES6-Namensemulation bereitstellen können, die keine große Leistungseinbuße hat, bin ich nicht an diesen Lösungen interessiert.

Eine Alternative wäre die Verwendung von Closures oder bind, aber dann würden Sie die Funktionen für jede Instanz mit einer erheblichen Leistungseinbuße neu erstellen. Eine andere Alternative wären die internen Eigenschaften des Namensraums wie __eventEmitter_events und __observable_state. Das ist nur hässlich und reduziert die Wahrscheinlichkeit eines Namespace-Konflikts, es wird nicht entfernt.

+0

gute Frage ..! – Alnitak

+0

Wenn Speicher dient, löst ExtJS es in der Objekterstellungs-Pipeline durch Instanziieren eines EventEmitter als eine Eigenschaft von der Observable hängen und alle * public * -Methoden des EventEmitter in die Observable mit Funktionsbindung Proxying, während alle private Status in diesem EventEmitter beibehalten . Ich würde ein Beispiel programmieren, aber ich werde AFK ... gib mir eine Stunde? – zetlen

+0

@zetlen Beachten Sie, dass das Proxys aller öffentlichen Methoden, die eine Funktionsbindung verwenden, bedeutet, dass Sie eine ganze Reihe neuer Funktionen für jede beobachtbare Instanz erstellen. Wie erwähnt, hat dies die exakte Leistungseinbuße bei der Emulation von privaten Namen. Dies ist eine Lösung, aber wir wollen sie aus Leistungsgründen vermeiden. – Raynos

Antwort

0

Die triviale Lösung ist "Namespaces"

var state = "[email protected]~state"; 
var Model = extend({}, Observable, { 
    constructor: function() { 
     // Nice, I used a namespace and don't clash with "[email protected]~state" 
     this[state] = { ... } 
    }, 
    someMethod: function() { ... } 
}) 
Verwandte Themen