web-dev-qa-db-fra.com

ES6 Noms de classe dynamiques

Je fais des expériences avec les classes ES6 et je me demande si vous pouvez changer les noms de classes de manière dynamique? Par exemple

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

Il y a probablement une meilleure solution pour tout ce que vous essayez d'atteindre, mais vous pouvez assigner une expression de classe à un objet:

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

Cela n'a pas vraiment changé dans ES2015: si vous voulez créer une liaison nommée de manière dynamique, vous devez utiliser un objet ou un autre mappage à la place.

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

Il y a un moyen assez simple de le faire:

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

Ici est la démo.

Il utilise un littéral d'objet pour définir un champ avec un nom souhaité pouvant contenir une nouvelle classe. Cela entraîne automatiquement le nom souhaité pour la nouvelle classe. Après quoi, nous extrayons cette nouvelle classe et la renvoyons.

Notez les parenthèses autour du littéral d'objet, de sorte que les accolades ne soient pas confondues avec un bloc de code (...) => {...}.

Bien sûr, le fait de placer une classe existante dans des champs nommés ne changera pas la classe. Cela ne fonctionne donc que si vous créez une nouvelle classe. Si vous avez seulement besoin d'un nom dynamique à un endroit où vous définissez la classe que vous nommez, vous pouvez supprimer un héritage supplémentaire et simplement aller:

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

Pour aller un peu plus loin en jouant avec les noms de classes dynamiques et l'héritage dynamique, vous pouvez utiliser babel comme suit:

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

Une façon, même si elle n’est pas idéale, est simple avec eval:

~function() {
    const name = "Lorem"

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

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

Notez que cela doit être avec var. Utiliser let, const et plain class dans eval ne fonctionnera pas.

Une autre façon avec Function:

~function() {
    const name = "Lorem"

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

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

Sitenote: vous pouvez passer des variables de portée dans la variable Function et les utiliser à l'intérieur de:

~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

L'exemple avec lequel j'ai lutté - résolu de la façon suivante:

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

et alors: 

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