Variablenvariablen der ES6-Klasse

492

Derzeit verwenden viele von uns in ES5 das folgende Muster in Frameworks, um Klassen und Klassenvariablen zu erstellen, was bequem ist:

// ES 5
FrameWork.Class({

    variable: 'string',
    variable2: true,

    init: function(){

    },

    addItem: function(){

    }

});

In ES6 können Sie Klassen nativ erstellen, es gibt jedoch keine Option für Klassenvariablen:

// ES6
class MyClass {
    const MY_CONST = 'string'; // <-- this is not possible in ES6
    constructor(){
        this.MY_CONST;
    }
}

Leider funktioniert das oben genannte nicht, da Klassen nur Methoden enthalten können.

Ich verstehe , dass ich kann this.myVar = trueinconstructor ... aber ich möchte meinen Konstruktor nicht "verschmutzen", besonders wenn ich 20-30 + Parameter für eine größere Klasse habe.

Ich habe über viele Möglichkeiten nachgedacht, mit diesem Problem umzugehen, aber noch keine guten gefunden. (Beispiel: Erstellen Sie einen ClassConfigHandler und übergeben Sie ein parameterObjekt, das separat von der Klasse deklariert ist. Dann würde der Handler an die Klasse angehängt. Ich habe darüber nachgedacht, WeakMapsauch irgendwie zu integrieren.)

Welche Ideen hätten Sie, um mit dieser Situation umzugehen?

Winterzähler
quelle
1
Ihr Hauptproblem ist, dass Sie this.member = memberbei Ihrem Konstruktor eine Wiederholung mit 20-30 Parametern haben?
Θεόφιλος Μουρατίδης
1
Kannst du nicht einfach public variable2 = trueunter Klasse verwenden? Dies würde es auf dem Prototyp definieren.
14
@ Θεόφιλος Μουρατίδης: Ja, und ich möchte meinen Konstruktor auch für Initialisierungsprozeduren und nicht für Variablendeklarationen verwenden.
Winterzähler
@derylius: Dies ist das Hauptproblem, es hat keine solche Funktion. Auch die öffentliche / private Nutzung ist im ES6-Entwurf noch nicht entschieden. Probieren
Wintercounter
Nach dem neuesten Stand hat es diese Funktion: wiki.ecmascript.org/doku.php?id=harmony:classes

Antworten:

515

Update 2018:

Es gibt jetzt einen Vorschlag für Stufe 3 - ich freue mich darauf, diese Antwort in einigen Monaten überflüssig zu machen.

In der Zwischenzeit kann jeder, der TypeScript oder babel verwendet, die folgende Syntax verwenden:

varName = value

Innerhalb eines Klassendeklarations- / Ausdruckskörpers wird eine Variable definiert. Hoffentlich kann ich in ein paar Monaten / Wochen ein Update veröffentlichen.

Update: Chrome 74 wird jetzt mit dieser Syntax ausgeliefert.


Die Notizen im ES-Wiki zum Vorschlag in ES6 ( maximal minimale Klassen ) Hinweis:

Es gibt (absichtlich) keine direkte deklarative Möglichkeit, entweder Prototypdateneigenschaften (außer Methoden), Klasseneigenschaften oder Instanzeigenschaften zu definieren

Klasseneigenschaften und Prototypdateneigenschaften müssen außerhalb der Deklaration erstellt werden.

In einer Klassendefinition angegebene Eigenschaften erhalten dieselben Attribute, als ob sie in einem Objektliteral erscheinen würden.

Das bedeutet, dass das wonach Sie fragen, berücksichtigt und ausdrücklich abgelehnt wurde.

aber warum?

Gute Frage. Die guten Leute von TC39 möchten, dass Klassendeklarationen die Fähigkeiten einer Klasse deklarieren und definieren. Nicht seine Mitglieder. Eine ES6-Klassendeklaration definiert ihren Vertrag für ihren Benutzer.

Denken Sie daran, dass eine Klassendefinition Prototypmethoden definiert. Das Definieren von Variablen auf dem Prototyp ist im Allgemeinen keine Aufgabe. Sie können natürlich verwenden:

constructor(){
    this.foo = bar
}

Im Konstruktor, wie Sie vorgeschlagen haben. Siehe auch die Zusammenfassung des Konsenses .

ES7 und darüber hinaus

Es wird an einem neuen Vorschlag für ES7 gearbeitet, der präzisere Instanzvariablen durch Klassendeklarationen und -ausdrücke ermöglicht - https://esdiscuss.org/topic/es7-property-initializers

Benjamin Gruenbaum
quelle
4
@wintercounter Das Wichtigste dabei ist, dass das Definieren von Eigenschaften diese auf dem Prototyp wie die Methoden und nicht auf jeder Instanz definiert. Maximal minimale Klassen sind immer noch das Kernstück der prototypischen Vererbung. Was Sie in Ihrem Fall wirklich tun möchten, ist die Freigabestruktur und die Zuweisung von Mitgliedern für jede Instanz. Dies ist einfach nicht das Ziel von Klassen in ES6 - das Teilen von Funktionen. Also ja, für die gemeinsame Nutzung der Struktur müssten Sie sich an die alte Syntax halten. Zumindest bis ES7 :)
Benjamin Gruenbaum
5
Vielleicht möchten Sie staticEigenschaften erwähnen
Bergi
8
Ups, Hirnfurz. Ich habe vergessen, dass staticdas auch nur für Methoden funktioniert.
Bergi
637
Vielleicht sollten die guten Leute bei TC39 dieses Konzept anders als "Klasse" nennen, wenn sie nicht möchten, dass es sich so verhält, wie es der Rest der Programmierwelt von etwas mit dem Namen "Klasse" erwartet.
Alex
7
Siehe auch den Vorschlag "Klassenfelder & statische Eigenschaften" (bereits in Babel implementiert : github.com/jeffmo/es-class-fields-and-static-properties
Matt Browne
127

Nur um Benjamins Antwort zu ergänzen: Klassenvariablen sind möglich, aber Sie würden sie nicht verwenden prototype, um sie festzulegen.

Für eine echte Klassenvariable möchten Sie Folgendes tun:

class MyClass {}
MyClass.foo = 'bar';

Innerhalb einer Klassenmethode kann auf diese Variable als this.constructor.foo(oder MyClass.foo) zugegriffen werden .

Auf diese Klasseneigenschaften kann normalerweise nicht von der Klasseninstanz aus zugegriffen werden. dh MyClass.foogibt 'bar'aber new MyClass().fooistundefined

Wenn Sie auch von einer Instanz aus auf Ihre Klassenvariable zugreifen möchten, müssen Sie zusätzlich einen Getter definieren:

class MyClass {
    get foo() {
        return this.constructor.foo;
    }
}

MyClass.foo = 'bar';

Ich habe dies nur mit Traceur getestet, aber ich glaube, dass es in einer Standardimplementierung genauso funktioniert.

JavaScript hat nicht wirklich Klassen . Selbst mit ES6 betrachten wir eher eine objekt- oder prototypbasierte Sprache als eine klassenbasierte Sprache. In jedem function X () {}, X.prototype.constructorzurück Punkte X. Wenn der newOperator verwendet wird X, wird ein neues Objekt erstellt, das erbt X.prototype. Alle undefinierten Eigenschaften in diesem neuen Objekt (einschließlich constructor) werden von dort aus nachgeschlagen. Wir können uns dies als Generierung von Objekt- und Klasseneigenschaften vorstellen.

lyschoening
quelle
29

Babel unterstützt Klassenvariablen in ESNext. Überprüfen Sie dieses Beispiel :

class Foo {
  bar = 2
  static iha = 'string'
}

const foo = new Foo();
console.log(foo.bar, foo.iha, Foo.bar, Foo.iha);
// 2, undefined, undefined, 'string'
Kosmetika
quelle
1
Sie können bar zu einer privaten Klassenvariablen machen, indem Sie sie mit "#" wie folgt vortäuschen: #bar = 2;
Lonnie Best
26

In Ihrem Beispiel:

class MyClass {
    const MY_CONST = 'string';
    constructor(){
        this.MY_CONST;
    }
}

Da MY_CONST primitiv ist https://developer.mozilla.org/en-US/docs/Glossary/Primitive , können wir einfach Folgendes tun:

class MyClass {
    static get MY_CONST() {
        return 'string';
    }
    get MY_CONST() {
        return this.constructor.MY_CONST;
    }
    constructor() {
        alert(this.MY_CONST === this.constructor.MY_CONST);
    }
}
alert(MyClass.MY_CONST);
new MyClass

// alert: string ; true

Wenn MY_CONSTes sich jedoch um einen Referenztyp handelt, bei dem die static get MY_CONST() {return ['string'];}Alarmausgabe eine Zeichenfolge ist, ist false . In diesem Fall deletekann der Bediener den Trick ausführen:

class MyClass {
    static get MY_CONST() {
        delete MyClass.MY_CONST;
        return MyClass.MY_CONST = 'string';
    }
    get MY_CONST() {
        return this.constructor.MY_CONST;
    }
    constructor() {
        alert(this.MY_CONST === this.constructor.MY_CONST);
    }
}
alert(MyClass.MY_CONST);
new MyClass

// alert: string ; true

Und schließlich für Klassenvariable nicht const:

class MyClass {
    static get MY_CONST() {
        delete MyClass.MY_CONST;
        return MyClass.MY_CONST = 'string';
    }
    static set U_YIN_YANG(value) {
      delete MyClass.MY_CONST;
      MyClass.MY_CONST = value;
    }
    get MY_CONST() {
        return this.constructor.MY_CONST;
    }
    set MY_CONST(value) {
        this.constructor.MY_CONST = value;
    }
    constructor() {
        alert(this.MY_CONST === this.constructor.MY_CONST);
    }
}
alert(MyClass.MY_CONST);
new MyClass
// alert: string, true
MyClass.MY_CONST = ['string, 42']
alert(MyClass.MY_CONST);
new MyClass
// alert: string, 42 ; true
Oleg Mazko
quelle
5
Bitte meiden Sie den deleteBetreiber, wenn auch aus Leistungsgründen. Was Sie hier eigentlich wollen, ist Object.defineProperty.
Bergi
@ Shinzou Ich dachte das gleiche. Nicht unbedingt die Schuld des OP; Es ist wirklich die Sprache, der es an geeigneten Mechanismen mangelt, um Daten auf eine Weise darzustellen, die ihre realen Beziehungen widerspiegelt.
user1974458
17

Da Ihr Problem hauptsächlich stilistisch ist (Sie möchten den Konstruktor nicht mit einer Reihe von Deklarationen füllen), kann es auch stilistisch gelöst werden.

So wie ich es sehe, ist der Konstruktor in vielen klassenbasierten Sprachen eine Funktion, die nach dem Klassennamen selbst benannt ist. Stilistisch könnten wir das verwenden, um eine ES6-Klasse zu erstellen, die stilistisch immer noch sinnvoll ist, aber die typischen Aktionen, die im Konstruktor stattfinden, nicht mit allen Eigenschaftsdeklarationen gruppiert, die wir ausführen. Wir verwenden einfach den eigentlichen JS-Konstruktor als "Deklarationsbereich" und erstellen dann eine Klasse mit dem Namen "Funktion", die wir ansonsten als "Bereich für andere Konstruktoren" behandeln, und rufen sie am Ende des wahren Konstruktors auf.

"benutze streng";

Klasse MyClass
{
    // deklariere nur deine Eigenschaften und rufe dann this.ClassName () auf; von hier
    Konstrukteur(){
        this.prop1 = 'bla 1';
        this.prop2 = 'bla 2';
        this.prop3 = 'bla 3';
        this.MyClass ();
    }}

    // alle möglichen anderen "Konstruktor" -Stücke, die nicht mehr mit Deklarationen durcheinander sind
    Meine Klasse() {
        mach was auch immer();
    }}
}}

Beide werden aufgerufen, wenn die neue Instanz erstellt wird.

Sorta mag es, zwei Konstruktoren zu haben, in denen Sie die Deklarationen und die anderen Konstruktoraktionen, die Sie ausführen möchten, trennen, und macht es stilistisch nicht allzu schwer zu verstehen, dass dies auch der Fall ist.

Ich finde, es ist ein guter Stil, wenn man sich mit vielen Deklarationen und / oder vielen Aktionen befasst, die bei der Instanziierung ausgeführt werden müssen, und wenn man die beiden Ideen voneinander unterscheiden möchte.


HINWEIS : Ich verwende sehr absichtlich nicht die typischen Redewendungen des "Initialisierens" (wie eine init()oder initialize()Methode), da diese oft unterschiedlich verwendet werden. Es gibt eine Art vermuteten Unterschied zwischen der Idee des Konstruierens und Initialisierens. Menschen, die mit Konstruktoren arbeiten, wissen, dass sie im Rahmen der Instanziierung automatisch aufgerufen werden. Wenn Sie eine initMethode sehen, gehen viele Leute ohne einen zweiten Blick davon aus, dass sie etwas in der Form von tun müssen var mc = MyClass(); mc.init();, denn so initialisieren Sie normalerweise. Ich bin nicht einen Initialisierungsprozess hinzufügen für den Benutzer der Klasse versucht, ich versuche zu addieren , um den Bauprozess der Klasse selbst.

Während einige Leute für einen Moment ein Double-Take machen, ist das eigentlich der springende Punkt: Es teilt ihnen mit, dass die Absicht Teil der Konstruktion ist, auch wenn sie dadurch ein bisschen Double-Take-and-Go machen "das ist nicht der Fall Wie ES6-Konstruktoren funktionieren "und nehmen Sie sich einen zweiten Blick auf den eigentlichen Konstruktor, um zu sagen" Oh, sie nennen es unten, wie ich sehe ", das ist weitaus besser, als diese Absicht NICHT zu kommunizieren (oder sie falsch zu kommunizieren) und wahrscheinlich viel davon zu bekommen Leute, die es falsch benutzen und versuchen, es von außen und Junk zu initialisieren. Das ist sehr beabsichtigt für das Muster, das ich vorschlage.


Für diejenigen, die diesem Muster nicht folgen möchten, kann auch das genaue Gegenteil funktionieren. Führen Sie die Deklarationen zu Beginn an eine andere Funktion aus. Nennen Sie es vielleicht "Eigenschaften" oder "publicProperties" oder so. Dann legen Sie den Rest des Materials in den normalen Konstruktor.

"benutze streng";

Klasse MyClass
{
    Eigenschaften() {
        this.prop1 = 'bla 1';
        this.prop2 = 'bla 2';
        this.prop3 = 'bla 3';
    }}

    Konstrukteur() {
        this.properties ();
        mach was auch immer();
    }}
}}

Beachten Sie, dass diese zweite Methode möglicherweise sauberer aussieht, aber auch ein inhärentes Problem aufweist, bei dem propertieseine Klasse, die diese Methode verwendet, eine andere erweitert. Sie müssten eindeutigere Namen angeben, um dies propertieszu vermeiden. Meine erste Methode hat dieses Problem nicht, da die gefälschte Hälfte des Konstruktors eindeutig nach der Klasse benannt ist.

Jimbo Jonny
quelle
1
Bitte verwenden Sie keine Prototypmethode, die nach der Klasse selbst benannt ist. Das ist in JS nicht idiomatisch. Versuchen Sie nicht, es wie eine andere Sprache aussehen zu lassen. Wenn Sie diesen Ansatz wirklich verwenden möchten, lautet der kanonische Name für die Methode init.
Bergi
1
@Bergi - initist ein Muster, das häufig verwendet wird und häufig von außerhalb der Klasse aufgerufen werden soll, wenn der externe Benutzer initialisieren möchte, d var b = new Thing(); b.init();. H. Dies ist eine 100% ige Stilwahl, die ich lieber mitteilen möchte, dass es sich um eine zweite Funktion handelt, die automatisch aufgerufen wird, indem die in anderen Sprachen gefundenen Muster ausgenutzt werden. Es ist weitaus weniger wahrscheinlich, dass jemand dies betrachtet und davon ausgeht, dass er die MyClassMethode von außen aufrufen muss , und eher, dass er erkennt, dass es sich bei der Absicht um eine zweite Methode handelt, die in der Konstruktion wirkt (dh bei der Instanziierung von selbst aufgerufen wird).
Jimbo Jonny
Hm, das könnte ich am Konstruktor erkennen, aber nicht am Methodennamen MyClass.
Bergi
1
@Bergi - Ein Muster aus einer anderen Sprache zu nehmen und es auf eine Weise auf JS anzuwenden, die technisch nicht das ist, was passiert, aber dennoch funktioniert, ist nicht völlig ohne Präzedenzfall. Sie können mir nicht sagen, dass niemand bemerkt hat, dass die $myvarStandardmethode zum Verweisen auf Variablen, die jQuery-Objekte enthalten sollen, nicht dem Muster ähnelt, $ am Anfang von Variablen zu haben, an das so viele PHP-Programmierer gewöhnt sind. Nur diese kleine Implikation, dass "Ja, es ist nicht genau das Gleiche ... aber sieh mal ... es ist immer noch eine Variable, denn auf diese Weise werden Variablen in einigen Sprachen erstellt!" hilft.
Jimbo Jonny
1
Ich bevorzuge Ihre letzte Option mit der properties()Funktion. Beim Erweitern von Klassen wird es jedoch etwas komplizierter. Wenn Sie properties()in allen Klassen eine Funktion zum Deklarieren von Klasseneigenschaften verwenden, wird dem Methodennamen der Klassenname (IE:) vorangestellt MyClassProperties(), um ein versehentliches Überschreiben zu vermeiden Funktionsaufrufe innerhalb von Unterklassen. super()
Beachten Sie
14

Was ist mit dem Oldschool-Weg?

class MyClass {
     constructor(count){ 
          this.countVar = 1 + count;
     }
}
MyClass.prototype.foo = "foo";
MyClass.prototype.countVar = 0;

// ... 

var o1 = new MyClass(2); o2 = new MyClass(3);
o1.foo = "newFoo";

console.log( o1.foo,o2.foo);
console.log( o1.countVar,o2.countVar);

Im Konstruktor erwähnen Sie nur die Variablen, die berechnet werden müssen. Ich mag die Vererbung von Prototypen für diese Funktion - sie kann helfen, viel Speicherplatz zu sparen (falls es viele nie zugewiesene Variablen gibt).

Zarkone
quelle
4
Dies spart keinen Speicher und verschlechtert die Leistung erheblich, als wenn Sie sie im Konstruktor deklariert hätten. codereview.stackexchange.com/a/28360/9258
Esailija
2
Dies macht auch den Zweck der Verwendung von ES6-Klassen in erster Linie zunichte. So wie es aussieht, scheint es kaum möglich zu sein, ES6-Klassen wie echte OOP-Klassen zu verwenden, was etwas enttäuschend ist ...
Kokodoko
4
@ Kokodoko real oop - du meinst, wie in Java? Ich stimme zu, ich habe bemerkt, dass viele Leute wütend auf JS sind, weil sie versuchen, es wie Java zu verwenden, wie sie es gewohnt sind, weil die JS-Syntax ähnlich aussieht und sie davon ausgehen, dass es genauso funktioniert ... Aber von das Innere ist es ganz anders, wie wir wissen.
Zarkone
2
Es geht aber nicht nur um die Sprachsyntax. Die OOP-Philosophie eignet sich sehr gut für die Programmierung im Allgemeinen - insbesondere beim Erstellen von Apps und Spielen. JS wurde traditionell beim Erstellen von Webseiten implementiert, was ganz anders ist. Irgendwie müssen diese beiden Ansätze zusammenkommen, da sich das Web auch mehr mit Apps befasst.
Kokodoko
1
@ Kokodoko Nur weil es ein anderes OOP ist, heißt das nicht, dass es kein OOP ist. Prototypen sind ein 100% -valider OOP-Ansatz. Niemand wird Self "non-OOP" nennen, weil es Prototypen verwendet. Nicht mit einem anderen OOP-Paradigma übereinzustimmen bedeutet genau das: Es ist anders.
Dave Newton
13

Wie Benjamin in seiner Antwort sagte, hat TC39 ausdrücklich beschlossen, diese Funktion zumindest für ES2015 nicht aufzunehmen. Der Konsens scheint jedoch zu sein, dass sie es in ES2016 hinzufügen werden.

Die Syntax wurde noch nicht festgelegt, aber es gibt einen vorläufigen Vorschlag für ES2016, mit dem Sie statische Eigenschaften für eine Klasse deklarieren können.

Dank der Magie von Babel können Sie dies heute nutzen. Aktivieren Sie die Transformation der Klasseneigenschaften gemäß diesen Anweisungen, und Sie können loslegen. Hier ist ein Beispiel für die Syntax:

class foo {
  static myProp = 'bar'
  someFunction() {
    console.log(this.myProp)
  }
}

Dieser Vorschlag befindet sich in einem sehr frühen Zustand. Seien Sie also bereit, Ihre Syntax im Laufe der Zeit zu optimieren.

BonsaiOak
quelle
Ja, das ist nicht ES6. Wenn Sie nicht wissen, was es ist, sollten Sie es nicht verwenden.
Bergi
10

[Langer Thread, nicht sicher, ob er bereits als Option aufgeführt ist ...].
Eine einfache Alternative nur für Contsants wäre die Definition der Konstante außerhalb der Klasse. Dies ist nur vom Modul selbst aus zugänglich, sofern es nicht mit einem Getter geliefert wird.
Dieser Weg prototypeist nicht verschmutzt und Sie bekommen die const.

// will be accessible only from the module itself
const MY_CONST = 'string'; 
class MyClass {

    // optional, if external access is desired
    static get MY_CONST(){return MY_CONST;}

    // access example
    static someMethod(){
        console.log(MY_CONST);
    }
}
Hertzel Guinness
quelle
Was passiert, wenn Sie a) a varanstelle von const2) mehrere Instanzen dieser Klasse verwenden? Dann werden die externen Variablen mit jeder Instanz der Klasse geändert
Nick Carraway
1
Fehlerpunkt @nickcarraway, mein Angebot steht nur für const, nicht als die Frage mit dem Titel.
Hertzel Guinness
6

ES7 Syntax der Klassenmitglieder:

ES7hat eine Lösung für das "Junking" Ihrer Konstruktorfunktion. Hier ist ein Beispiel:

class Car {
  
  wheels = 4;
  weight = 100;

}

const car = new Car();
console.log(car.wheels, car.weight);

Das obige Beispiel würde wie folgt aussehen ES6:

class Car {

  constructor() {
    this.wheels = 4;
    this.weight = 100;
  }

}

const car = new Car();
console.log(car.wheels, car.weight);

Beachten Sie bei der Verwendung, dass diese Syntax möglicherweise nicht von allen Browsern unterstützt wird und möglicherweise in einer früheren Version von JS transpiliert werden muss.

Bonus: eine Objektfabrik:

function generateCar(wheels, weight) {

  class Car {

    constructor() {}

    wheels = wheels;
    weight = weight;

  }

  return new Car();

}


const car1 = generateCar(4, 50);
const car2 = generateCar(6, 100);

console.log(car1.wheels, car1.weight);
console.log(car2.wheels, car2.weight);

Willem van der Veen
quelle
3
Sie haben Instanzvariablen erstellt, keine Klassenvariablen.
Tjad Clark
5

Sie können das Verhalten von es6-Klassen nachahmen ... und Ihre Klassenvariablen verwenden :)

Schau Mama ... kein Unterricht!

// Helper
const $constructor = Symbol();
const $extends = (parent, child) =>
  Object.assign(Object.create(parent), child);
const $new = (object, ...args) => {
  let instance = Object.create(object);
  instance[$constructor].call(instance, ...args);
  return instance;
}
const $super = (parent, context, ...args) => {
  parent[$constructor].call(context, ...args)
}
// class
var Foo = {
  classVariable: true,

  // constructor
  [$constructor](who){
    this.me = who;
    this.species = 'fufel';
  },

  // methods
  identify(){
    return 'I am ' + this.me;
  }
}

// class extends Foo
var Bar = $extends(Foo, {

  // constructor
  [$constructor](who){
    $super(Foo, this, who);
    this.subtype = 'barashek';
  },

  // methods
  speak(){
    console.log('Hello, ' + this.identify());
  },
  bark(num){
    console.log('Woof');
  }
});

var a1 = $new(Foo, 'a1');
var b1 = $new(Bar, 'b1');
console.log(a1, b1);
console.log('b1.classVariable', b1.classVariable);

Ich habe es auf GitHub gestellt

Ruslan
quelle
0

Die Art und Weise, wie ich dies gelöst habe, ist eine weitere Option (wenn Sie jQuery zur Verfügung haben), die Felder in einem Old-School-Objekt zu definieren und dann die Klasse mit diesem Objekt zu erweitern. Ich wollte den Konstruktor auch nicht mit Aufgaben überhäufen, dies schien eine ordentliche Lösung zu sein.

function MyClassFields(){
    this.createdAt = new Date();
}

MyClassFields.prototype = {
    id : '',
    type : '',
    title : '',
    createdAt : null,
};

class MyClass {
    constructor() {
        $.extend(this,new MyClassFields());
    }
};

- Update Nach Bergis Kommentar.

Keine JQuery-Version:

class SavedSearch  {
    constructor() {
        Object.assign(this,{
            id : '',
            type : '',
            title : '',
            createdAt: new Date(),
        });

    }
}

Sie haben immer noch einen "fetten" Konstruktor, aber zumindest ist alles in einer Klasse und in einem Treffer zugewiesen.

EDIT # 2: Ich habe jetzt den Kreis geschlossen und weise jetzt Werte im Konstruktor zu, z

class SavedSearch  {
    constructor() {
        this.id = '';
        this.type = '';
        this.title = '';
        this.createdAt = new Date();
    }
}

Warum? Mit den oben genannten und einigen JSdoc-Kommentaren konnte PHPStorm die Code-Vervollständigung für die Eigenschaften durchführen. Das Zuweisen aller Variablen in einem Treffer war nett, aber die Unfähigkeit, die Eigenschaften vollständig zu codieren, ist den (mit ziemlicher Sicherheit winzigen) Leistungsvorteil nicht wert.

Steve Childs
quelle
2
Wenn Sie classSyntax ausführen können, können Sie dies auch tun Object.assign. Keine Notwendigkeit für jQuery.
Bergi
Ich sehe keinen Grund, MyClassFieldseinen Konstruktor zu erstellen - er hat keine Methoden. Können Sie erläutern, warum Sie dies getan haben (anstelle von beispielsweise einer einfachen Factory-Funktion, die ein Objektliteral zurückgibt)?
Bergi
@Bergi - Um ehrlich zu sein, wahrscheinlich eher Gewohnheit als irgendetwas anderes. Auch netter Anruf über Object.assign - wusste nichts davon!
Steve Childs
0

Nun, Sie können Variablen im Konstruktor deklarieren.

class Foo {
    constructor() {
        var name = "foo"
        this.method = function() {
            return name
        }
    }
}

var foo = new Foo()

foo.method()
Osama Xäwãñz
quelle
1
Sie müssen eine Instanz dieser Klasse erstellen, um diese Variable verwenden zu können. Statische Funktionen können nicht auf diese Variable zugreifen
Aditya
0

Trotzdem können Sie keine Klassen wie in anderen Programmiersprachen deklarieren. Sie können jedoch beliebig viele Klassenvariablen erstellen. Das Problem ist jedoch der Umfang des Klassenobjekts. Also meiner Meinung nach Bester Weg OOP-Programmierung in ES6 Javascript: -

class foo{
   constructor(){
     //decalre your all variables
     this.MY_CONST = 3.14;
     this.x = 5;
     this.y = 7;
     // or call another method to declare more variables outside from constructor.
     // now create method level object reference and public level property
     this.MySelf = this;
     // you can also use var modifier rather than property but that is not working good
     let self = this.MySelf;
     //code ......... 
   }
   set MySelf(v){
      this.mySelf = v;
   }
   get MySelf(v){
      return this.mySelf;
   }
   myMethod(cd){
      // now use as object reference it in any method of class
      let self = this.MySelf;
      // now use self as object reference in code
   }
}
Tyler
quelle
-1

Dies ist eine etwas hackige Kombination aus statischer Aufladung und funktioniert für mich

class ConstantThingy{
        static get NO_REENTER__INIT() {
            if(ConstantThingy._NO_REENTER__INIT== null){
                ConstantThingy._NO_REENTER__INIT = new ConstantThingy(false,true);
            }
            return ConstantThingy._NO_REENTER__INIT;
        }
}

anderswo verwendet

var conf = ConstantThingy.NO_REENTER__INIT;
if(conf.init)...
TroyWorks
quelle
7
Ich würde singleton_instanceals Eigenschaftsnamen empfehlen, damit jeder versteht, was Sie hier tun.
Bergi