547 Stimmen

ES6 Klassenvariablen-Alternativen

Aktuell 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 Klassen nativ erstellt werden, es gibt jedoch keine Option für Klassenvariablen:

// ES6
class MyClass {
    const MY_CONST = 'string'; // <-- dies ist in ES6 nicht möglich
    constructor(){
        this.MY_CONST;
    }
}

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

Ich verstehe, dass ich this.myVar = true im constructor verwenden kann ... aber ich möchte meinen Konstruktor nicht 'verunreinigen', besonders wenn ich 20-30+ Parameter für eine größere Klasse habe.

Ich habe über viele Möglichkeiten nachgedacht, dieses Problem zu lösen, aber noch keine guten gefunden. (Zum Beispiel: Erstellen eines ClassConfig-Handlers und Übergeben eines parameter-Objekts, das separat von der Klasse deklariert wird. Dann würde der Handler an die Klasse angehängt werden. Ich habe auch über die Integration von WeakMaps nachgedacht.)

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

14voto

BonsaiOak Punkte 24641

Wie Benjamin in seiner Antwort sagte, hat TC39 explizit beschlossen, dieses Feature zumindest nicht für ES2015 einzuschließen. Die 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, der es ermöglichen wird, statische Eigenschaften in einer Klasse zu deklarieren.

Dank der Magie von Babel kannst du dies bereits heute verwenden. Aktiviere die Klasseneigenschaften-Transformation gemäß diesen Anweisungen und du bist startklar. Hier ist ein Beispiel für die Syntax:

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

Dieser Vorschlag befindet sich in einem sehr frühen Stadium, also sei bereit, deine Syntax im Laufe der Zeit anzupassen.

13voto

zarkone Punkte 1315

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 dieses Feature - es kann dazu beitragen, eine Menge Speicher zu sparen (für den Fall, dass es viele nie zugewiesene Variablen gibt).

11voto

Hertzel Guinness Punkte 5742

[Langer Thread, nicht sicher, ob er bereits als Option aufgeführt ist...].
Eine einfache Alternative nur für Konstanten wäre, die Konstante außerhalb der Klasse zu definieren. Dies ist nur aus dem Modul selbst zugänglich, es sei denn, es wird mit einem Getter begleitet.
Auf diese Weise ist das Prototyp nicht überladen und Sie erhalten die const.

// Wird nur aus dem Modul selbst zugänglich
const MY_CONST = 'Zeichenfolge'; 
class MyClass {

    // Optional, wenn externer Zugriff erwünscht ist
    static get MY_CONST(){return MY_CONST;}

    // Zugriffsbeispiel
    static someMethod(){
        console.log(MY_CONST);
    }
}

10voto

Willem van der Veen Punkte 26043

ES7 Klassensyntax:

ES7 hat eine Lösung für das 'Verschrotten' 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 im ES6 wie folgt aussehen:

class Car {

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

}

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

Seien Sie sich bewusst, dass diese Syntax möglicherweise nicht von allen Browsern unterstützt wird und möglicherweise in eine frühere 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);

5voto

Ruslan Punkte 199

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

Schau Mama... keine Klassen!

// 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 'Ich bin ' + this.me;
  }
}

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

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

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

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 hochgeladen

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X