web-dev-qa-db-fra.com

Instance de classe anonyme ---- est-ce une mauvaise idée?

Dans ES6, nous pouvons faire une classe anonyme:

var entity = class {
}

Mais on peut aussi l'instancier:

var entity = new class {
    constructor(name) { this.name = name; }
    getName() { return this.name; }
}('Foo');
console.log(entity.getName()); // Foo

Que fait-on derrière, quel avantage cela apportera-t-il et quelles mises en garde apportera-t-il également?

23
Steve Fan

Instance de classe anonyme - est-ce une mauvaise idée?

Oui, très mauvais. Juste aussi mauvais que new function() { … } était dans ES5 .

Ce style d'écriture conduit à la création d'une nouvelle fonction constructeur et d'un objet prototype à chaque fois que l'expression est évaluée. Si vous créez plusieurs objets avec cette approche, ils n'obtiendront aucun des avantages des classes/prototypes.

Si vous vouliez que ce modèle crée un objet singleton, vous avez également échoué. Le constructeur est toujours créé, et il est même accessible - une deuxième instance peut être facilement créée en utilisant new entity.constructor, détruisant tout le but.

Donc ne l'utilisez jamais . Un littéral d'objet simple est beaucoup plus facile à écrire, à lire et à instancier:

var entity = {
    name: 'Foo',
    getName() { return this.name; }
};
console.log(entity.name); // Foo

Ne vous laissez pas berner par d'autres langues où le new class le modèle est courant, il fonctionne très différemment de celui-ci en JavaScript.

37
Bergi

Vous voudrez peut-être des classes anonymes si vous savez exactement ce que vous faites, vous créez une hiérarchie de classes (c'est-à-dire des choses dont vous voulez des copies) dans un système de métaprogrammation bien pensé, et il n'y a pas d'autre solution élégante à l'extension, par exemple.

{
    myImplementation: class extends MyBaseClass {
        someMethod(x) {
            super().someMethod(x);
            insert extended behavior
        }
    }
}

Bien sûr, vous pouvez implémenter ce qui précède avec certaines fonctions magiques abusives qui utilisent Object.assign:

{
    myImplementation: extendMagic(mySuper => ({
        someMethod(x) {
            mySuper.someMethod(x);
            insert extended behavior
        }
    }))
}

ou trouver une meilleure façon de faire ce que vous faites. Mais des cas d'utilisation artificiels existeront occasionnellement (bien que rarement).

Les cas d'utilisation ne sont jamais excellents, mais sont plus convaincants lorsque vous avez besoin de fonctionnalités de classe qui sont plus difficiles à écrire avec l'héritage prototypique (et bien sûr, puisque les classes sont en quelque sorte des enveloppes autour de l'héritage prototypique, votre cas d'utilisation se résume à vouloir le sucre syntaxique plus fonctionnalités de la classe es6 + ... voulez-vous des constructeurs et des super et des extensions et des méthodes statiques, etc ... ou pas? Êtes-vous coincé à travailler avec des classes qui existent déjà, ou pouvez-vous tout écrire en utilisant des objets et des assertions? Et faut-il vraiment être anonyme? Ces questions peuvent vous aider à décider.).

3
ninjagecko