J'écris une fonction qui prend des classes et retourne une classe avec une seule classe qui peut être étendue, mais je suis récemment passé au transpilateur babel, et j'ai réalisé que je ne suis pas censé appeler les constructeurs de classe sans nouveau,

Y a-t-il un moyen de contourner cela qui fonctionnerait également dans le vrai es6?

Voici ma fonction multiple

Object.getOwnPropertySymbols;

module.exports = function multiple(_classes){
    class MultipleClasses{}

    for (const {obj:_class} of iterateObject(_classes)){
        const prototypeChain = [];
        let prototype = _class.prototype;
        do{
            prototypeChain.push(prototype);
        }
        while((prototype = prototype.__proto__) !== null)
        prototypeChain.reverse();
        for (const prototype of prototypeChain){
            assignNonEnumerable(MultipleClasses.prototype, prototype);
        }
    }

    for (const {key, obj:_class} of iterateObject(_classes)){
        MultipleClasses.prototype[key] = _class.prototype.constructor;
    }

    return MultipleClasses;
}

function* iterateObject(obj){
    const keys = Object.getOwnPropertyNames(obj);
    for (const key of keys){
        yield {key, obj:obj[key]};
    }
}

function assignNonEnumerable(target, source){
    const keys = Object.getOwnPropertyNames(source);
    for (const key of keys){
        Object.defineProperty(target, key, {
            enumerable:false,
            writable:true,
            configurable:true,
            value:source[key]
        });
    }
    const symbols = getOwnPropertySymbols(source);
    for (const symbol of symbols){
        Object.defineProperty(target, symbol, {
            enumerable:false,
            writable:true,
            configurable:true,
            value:source[symbol]
        }); 
    }
}

Et pour étendre les classes que j'utilise

class Player extends multiple({Physical, Circle}) {
    constructor(_x, _y, input){
        super();
        super.Physical(_x, _y)
        super.Circle(_x, _y, playerRadius);
...

Y a-t-il un moyen d'obtenir super pour appeler plusieurs fonctions ou quelque chose?

0
Jim Jones 16 juil. 2015 à 01:17

2 réponses

Meilleure réponse

Il est nécessaire à 100% que les constructeurs de classe dans ES6 soient appelés via new Constructor() ou via super(). Il n'y a pas moyen de contourner cela, car ce comportement est essentiel pour que les moteurs JavaScript puissent construire le type d'objet approprié.

Pour votre cas, disons que Circle était

class Circle extends Array {}

Votre code se cassera car l'objet créé par

new Player()

Ne sera pas un objet tableau. Cela s'applique à toutes les sous-classes natives et c'est la raison pour laquelle new est nécessaire.

Si vous voulez que quelque chose soit une combinaison de plusieurs ensembles de fonctions, vous devrez composer manuellement ces fonctions ensemble à partir d'objets standard.

1
loganfsmyth 15 juil. 2015 à 22:43

Bien que le nouveau puisse être "dangereux", si vous construisez vos classes avec certains gardes, vous pouvez toujours utiliser des classes. Oui, c'est un peu bizarre et les "Good Part" -ists tournent le nez, mais j'ai l'impression que les classes sont toujours une victoire dans l'ensemble.

class Player {
  constructor(/*args...*/) {
    if(!(this instanceof Player)) {
      return new Player(/*args...*/);
    }
  }
}

var player1 = Player("Spencer");
var player2 = new Player("Other guy")
0
Hath995 15 juil. 2015 à 23:58