2017-12-05 1 views
0

Ich habe einige Code:Klasse statische Getter, die Klasse in Javascript gibt

//Main class 
class Tools { 

    //Subclass implemented by static getter 
    static get SUPPORTED_UNITS() { 
    return class { 
     //Another one 
     static get Size() { 
     return class { 
      //Some data (constants in my case) 
     }; 
     } 
    }; 
    } 
} 

Ich will, es zu benutzen wie Tools.SUPPORTED_UNITS.Size und ich möchte einige Daten als Folge davon empfangen. Ich benutze WebStorm zum Schreiben von JavaScript-Code, so dass es mir zeigt, wenn ich es benutze.

Screenshot of error

ich nicht genau wissen, vielleicht habe ich, nur nicht einige Setup meiner WebStorm getan, aber .. Was muss ich tun, dass ich Konstruktion wie Class.Subclass.SubClassMethod/SubSubclass verwenden können.

Ich brauche das:

  • Es ist keine Methode
  • Es
  • Es ist unveränderlich (ohne Object.freeze oder so ähnlich) statisch sein - so kann ich nicht meine Class.Subclass ändern von Class.Subclass = foo;
  • eingeben sein Es Indizierung von IDE - so habe ich etwas Hilfe von IDE (wie ich Class.Su geben und sie legen nahe, Class.Subclass)

Ist es in ES6 und WebStorm real? Oder muss ich vielleicht ES7 und Babel oder sowas benutzen?

P.S. Dieser Code ist funktioniert, aber ich brauche Anregungen von IDE oder es wird wie eine Hölle sein.

+0

Da der Code funktionsfähig ist und keine ES2016 + -Features verwendet, können Sie sicher sein, dass es sich um ES6 handelt, und das Problem ist spezifisch für die IDE. Der Code erklärt nicht, warum eine Klasse * innerhalb * einer Methode definiert werden sollte, dies führt möglicherweise zu einem XY-Problem. – estus

+2

Verwenden Sie keine Klassen, wenn Sie nur statische Methoden implementieren. Verwenden Sie stattdessen ein normales Objekt: 'const Tools = {SUPPORTED_UNITS: {Size: {}}}'.Sie können Getter auch für Objekte definieren, wenn Sie das brauchen. Ich empfehle, http://eloquentjavascript.net/04_data.html zu lesen. Was Sie implementieren, ist auch keine "Unterklasse". Eine Unterklasse ist normalerweise eine Klasse, die * eine Basisklasse * erweitert. –

+0

@estus Ich denke, dass es eine Unterklassen für die Verwendung von Getter benötigt, die nicht erlauben, Daten im Inneren zu ändern. Vielleicht denke ich falsch (es ist normal, weil ich gerade anfange tief zu gehen). Wie muss ich meine Klasse schreiben, um unveränderliche statische Daten zu verwenden? Beispiel: 'Tools.SUPPORTED_UNITS.Size', wobei ich ** nichts ändern kann (schreibe' Tools.SUPPORTED_UNITS = foo'). Danke –

Antwort

0

Nach @estus und @Felix Kling Vorschlag ... (wahrscheinlich hier falsch dargestellt wird)

const TOOLS = { 
    get SUPPORTED_UNITS() { 
     return { 
      get SIZE() { 
       return { 
        get Bar() { 
         return 1; 
        } 
       } 
      } 
     } 
    } 
}; 
console.log(TOOLS.SUPPORTED_UNITS.SIZE.Bar) // 1; 

TOOLS.SUPPORTED_UNITS.SIZE = "Hello"; 
// TOOLS.SUPPORTED_UNITS.SIZE = "Hello"; 
//       ^
// TypeError: Cannot set property SIZE of #<Object> which has only a getter 

Das funktioniert aber wie durch @bergi bemerkte, es erzeugt ein neues Objekt in jedem Nachschlag:

console.log(TOOLS.SUPPORTED_UNITS === TOOLS.SUPPORTED_UNITS); // false 

Yep ...

eine Alternative noch Getter verwendet würden alle diese Objekte in einer IIFE sein kapseln:

const TOOLS = (function() { 
    const SIZE = { 
     get Bar() { return 1; } 
    } 
    const SUPPORTED_UNITS = { 
     get SIZE() { 
      return SIZE; 
     } 
    } 
    return { 
     get SUPPORTED_UNITS() { 
      return SUPPORTED_UNITS; 
     } 
    } 
}()); 

console.log(TOOLS.SUPPORTED_UNITS.SIZE.Bar === TOOLS.SUPPORTED_UNITS.SIZE.Bar); // true 
console.log(TOOLS.SUPPORTED_UNITS.SIZE === TOOLS.SUPPORTED_UNITS.SIZE); // true 
console.log(TOOLS === TOOLS); // true 

TOOLS.SUPPORTED_UNITS = "hello"; // still throws an error 

Drittes Update:

Das zweite Beispiel löst das Problem auf die Schaffung eines neuen Objekts im Zusammenhang jeder Lookup, aber es braucht auch nicht in Betracht, dass der Zugriff auf alle verschachtelten Eigenschaft führt zu einer Funktion rufen etwas neu zu bewerten, die nicht soll sich ändern:

//A naive measurement: 
for(let counter = 0; counter < 5; counter++) { 
    let start = Date.now();  
    for(let i = 0; i < 200000; i++){ 
     let somevar = Tools.SUPPORT_UNITS.SIZE; 
    } 
    let end = Date.now(); 
    console.log(`Elapsed using nested getters: ${end - start}ms.`); 
} 
// Something like: 
/** Elapsed using nested getters: 20ms. 
* Elapsed using nested getters: 14ms. 
* Elapsed using nested getters: 9ms. 
* Elapsed using nested getters: 10ms. 
* Elapsed using nested getters: 10ms. 
* 
// While the same as ordinary properties: 
* Elapsed ordinary properties: 2ms. 
* Elapsed ordinary properties: 5ms. 
* Elapsed ordinary properties: 1ms. 
* Elapsed ordinary properties: 0ms. 
* Elapsed ordinary properties: 0ms. 
*/ 

So ist es auch bessere Alternativen zu prüfen, bevor mit diesem Ansatz, wenn 200000 Laufzeiten Schleifen in absehbarer Zukunft.

+0

Sie wollen sicherlich nicht einmal Getter verwenden. Sie würden das Objekt bei jedem Zugriff neu erstellen. – Bergi

+0

ja, du hast Recht @bergi –

+0

@betadeveloper Was denkst du über die Verwendung von deepFreeze fuction? Machen Sie ein Objekt, deepFreezed es => gab etwas wie statische Objekt –