2015-02-03 24 views
24

Esiste un modo per utilizzare la notazione ECMAScript6 class per dichiarare una variabile di classe statica o un valore predefinito per una variabile di istanza? Senza class quello che ho in mente sarebbe scritto comeVariabili membro nelle classi ES6

function MyClass(arg) { if(arg) this.arg = arg; } 
MyClass.classVariable = 42; 
MyClass.prototype.arg = "no arg specified"; 

La più ovvia notazione ES6-come a mio avviso sarebbe stato

class MyClass { 
    constructor(arg) { if(arg) this.arg = arg; } 
    static let classVariable = 42; 
    let arg = "no arg specified"; 
} 

Ma questo non funziona, dal momento che secondo il the current spec draft solo le produzioni di ClassElement sono statici e metodi di istanza e punto e virgola da soli. OK, si può usare un paio di metodi getter e setter per ottenere una semantica simile a quello che ho delineato, ma credo che con una severa penalizzazione delle prestazioni e con una sintassi davvero bizzarra.

C'è qualche bozza che suggerisce di includere variabili nella notazione class, in un modo o nell'altro? In tal caso, qual è stata la sintassi suggerita, dove è stata pubblicata, dove è stato discusso, come è andata la discussione e qual è lo stato attuale delle cose su questo fronte? Così com'è, questa domanda non può essere risolta se nessuna di queste cose è stata discussa prima, a qualsiasi livello, ma lo ritengo improbabile.

Un po 'di background: attualmente sto giocando con il compilatore di chiusura Google eseguendo una compilazione avanzata, utilizzando ES6 come input. Perché funzioni, ho bisogno di un posto dove inserire le mie annotazioni di tipo per le variabili membro, e le ho usate usando la sintassi come /** @type {string} */ MyClass.prototype.arg; che è un no-sem semantico in ECMAScript ma fornisce le informazioni sul tipo al compilatore di chiusura semplice e facile. Non ho ancora trovato un modo altrettanto piacevole per farlo con un costrutto class. Ma se ti interessa affrontare questo aspetto, quello sarebbe un commento. La domanda di cui sopra riguarda le dichiarazioni dei membri che sono più che non opzionali, quindi è qui che dovrebbe rispondere una risposta.

+2

penso 'class Foo {get foo() {return 123}}' è più vicino come si ottiene – kangax

+0

Penso che la tecnica di @ kangax sia la migliore scommessa per qualsiasi cosa che agirà come una classe astratta. Ho avuto lo stesso problema; ecco un controller che ho scritto che può/non può darti alcune idee. Il costruttore della classe base fa tutto il lavoro pesante per funzionalità uniche (in questo caso unire gli array), quindi devi solo assicurarti che 'super()' sia sempre chiamato sui costruttori subclass: https://github.com/ affirmix/tungstenjs/blob/master/src/controller.js. Puoi vedere che le sottoclassi non sembrano troppo sgradevoli: https://github.com/affirmix/tungstenjs-todomvc/blob/master/src/todoitem-controller.j –

risposta

29

ES6 non coprirà quasi certamente la sintassi per la definizione delle variabili di classe. Solo i metodi e i getter/setter possono essere definiti utilizzando la sintassi della classe. Ciò significa che dovrai ancora percorrere la route MyClass.classVariable = 42; per le variabili di classe.

Se si desidera inizializzare una classe con alcune impostazioni predefinite, è disponibile un nuovo set di sintassi ricco per l'argomento della funzione e i valori predefiniti di destrutturazione che è possibile utilizzare. Per fare un semplice esempio:

class Foo { 
    constructor(foo = 123) { 
     this.foo = foo; 
    } 
} 

new Foo().foo == 123 
new Foo(42).foo == 42 
+0

Questo approccio non funziona se tu Stai accedendo alle proprietà della classe impostate nel costruttore in altre funzioni. Vedi http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback – Jacob

+0

@Jacob nell'esempio che ho dato che non sto impostando le proprietà della classe nel costruttore, ma piuttosto una proprietà di istanza con un valore predefinito. Tuttavia, se si desidera accedere a una proprietà di classe da una funzione dell'istanza, è possibile accedervi utilizzando 'this.constructor.classProperty'. – lyschoening

+0

[Le definizioni del corpo e dei metodi di classe] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Class_body_and_method_definitions) ha la sezione ** Metodi prototipo **. –

5

Non ho usato Google Closure Compiler, ma con Babel è possibile dichiarare static (ambito a un class) variabili come descritto here. L'articolo è incentrato su React a causa dell'utilità dei membri static per React, ma è applicabile a ES6 class in generale.

sintassi è vicino alla vostra sintassi proposto:

class MyClass { 
    constructor(arg) { if(arg) this.arg = arg; } 
    static defaultArg = 42; 
    let arg = MyClass.defaultArg; 
} 

noti che dovrete aggiungere al vostro 'es7.classProperties'.babelrc per questo compilare. Vedi lo Babel 5.0.0 release notes per maggiori informazioni.

Non so se esiste un modo per dichiarare uno static come const.

3

Anche se non fa parte delle specifiche ES6, sembra che arriverà presto ed è già supportato da Babel e da altri.

Ecco le specifiche: https://github.com/jeffmo/es-class-fields-and-static-properties

e un elenco completo di tutte le proposte e il loro stato: https://github.com/tc39/ecma262

+0

"sembra che arriverà in ES7" sicuramente non funziona, il set di funzionalità è finalizzato e consiste solo di 2 proposte stage-4. – zerkms

+0

@zerkms hai assolutamente ragione, ho modificato la mia risposta, grazie per la correzione! Non avevo realizzato che es7 fosse stato finalizzato. –