wake-up-neo.net

ES6 Dynamische Klassennamen

Ich habe mit ES6-Klassen experimentiert und frage mich, ob Sie Klassennamen dynamisch ändern können. Zum Beispiel

class [Some dynamic name] {}; 
32
simon-p-r

Es gibt wahrscheinlich eine bessere Lösung für alles, was Sie erreichen möchten, aber Sie können einem Objekt einen Klassenausdruck zuweisen:

let classes = {};
classes[someName] = class { ... };

Dies hat sich in ES2015 nicht wirklich geändert: Wenn Sie eine dynamisch benannte Bindung erstellen möchten, müssen Sie stattdessen ein Objekt oder eine andere Zuordnung verwenden.

19
Felix Kling
let C = class
{ // ...
}
Object.defineProperty (C, 'name', {value: 'TheName'});

// test: 
let itsName =  (new C()).constructor.name;
// itsName === 'TheName' -> true
12
Panu Logic

Es gibt eine ziemlich einfache Möglichkeit, dies zu tun:

const nameIt = (name, cls) => ({[name] : class extends cls {}})[name];

Hier / s ist die Demo.

Es verwendet ein Objektliteral, um ein Feld mit einem gewünschten Namen zu definieren, der eine neue Klasse enthalten würde. Dadurch erhält die neue Klasse automatisch den gewünschten Namen. Nachdem wir damit fertig sind, extrahieren wir die neue Klasse und geben sie zurück.

Beachten Sie die Parens um das Objektliteral, sodass geschweifte Klammern nicht mit einem Codeblock (...) => {...} verwechselt werden.

Wenn Sie eine vorhandene Klasse in benannte Felder einfügen, wird die Klasse natürlich nicht geändert. Dies funktioniert also nur, wenn Sie eine neue Klasse erstellen. Wenn Sie nur einen dynamischen Namen an einer Stelle benötigen, an der Sie die Klasse definieren, die Sie benennen, können Sie eine zusätzliche Vererbung löschen und gehen einfach:

const myClass = {[name]: class {
    ...
}}[name];
6
Daerdemandt

Um mit dynamischen Klassennamen und dynamischer Vererbung ein wenig weiter zu spielen, können Sie bei der Verwendung von Babel Folgendes tun:

    function withname(name, _parent) {
        return class MyDinamicallyNamedClass extends (_parent||Object) {
            static get name() { return name || _parent.name }
        }
    }
4
Anibal Ambertin

Eine Möglichkeit, wenn auch nicht ideal, ist mit eval einfach:

~function() {
    const name = "Lorem"

    eval(`
        var ${name} = class ${name} {} 
    `)

    console.log(Lorem) // class Lorem {}
}()

Beachten Sie, es muss mit var sein. Die Verwendung von let, const und plain class in eval funktioniert nicht.

Ein anderer Weg mit Function:

~function() {
    const name = "Lorem"

    const c = new Function(`
        return class ${name} {}
    `)()

    console.log(c) // class Lorem {}
}()

Sitenote: Sie können Bereichsvariablen in die Variable Function übergeben und sie innerhalb von verwenden:

~function() {
    const name = "Lorem"
    const val = "foo"

    const Class = new Function('val', `
        return class ${name} {
            constructor() {
                console.log( val )
            }
        }
    `)( val )

    console.log(Class) // class Lorem {}
    new Class // "foo"
}()
2
trusktr

Das Beispiel, mit dem ich zu kämpfen hatte - wurde auf folgende Weise gelöst:

const models = {
  route: mongoose.model('Route'),
  company: mongoose.model('Company'),
  ...
}

und dann: 

const name = 'route'
const record = new models[name]()
0
Greg Woz