web-dev-qa-db-fra.com

Méthode appropriée pour ajouter dynamiquement des fonctions aux classes ES6

J'ai une classe simple avec une seule méthode exec(arg1,..,argn) et je veux avoir un certain nombre de méthodes d'alias qui appellent exec avec des valeurs d'argument prédéfinies (par exemple, exec_sync = exec.bind(this, true)). 

Ce qui suit fait l'affaire:

class Executor {
  constructor() {
    this.exec_sync = this.exec.bind(this, true);
  }

  exec(sync, cmd, args/* ... */) {
    // impl
  }
}

Mais Je ne sais pas si c'est une bonne idée ou si c'est idiomatique pour ES6.

UDATE:

Dans un exemple concret, j'ai deux boucles imbriquées avec respectivement 3 et 4 boucles, qui sont utilisées pour ajouter dynamiquement un nombre total de 12 méthodes d'alias à la classe. Il serait fastidieux de définir explicitement les méthodes de pseudonymes lorsque vous pouvez réellement tirer parti de l'utilisation de JS comme langage de programmation basé sur un prototype.

MISE À JOUR 2 - EXEMPLE:

Supposons que nous ayons un client HTTP simple avec une méthode request(method, body) et que nous voulions fournir des méthodes d'alias pour GET, PUT, etc. Cela ressemblerait à quelque chose comme:

class HTTP {
  constructor() {
    ['GET', 'PUT', 'POST', 'DEL'].forEach((method) => {
      this[method] = this.request.bind(this, method);
    }, this);
  }

  request(method, body) {
    // execute the HTTP request
  }
}
18
Yan Foto

Votre solution est satisfaisante, mais il sera préférable de créer toutes ces méthodes une fois au niveau prototype:

['GET', 'PUT', 'POST', 'DEL'].forEach((method) => {
  Executor.prototype[method] = function (body) {
    return this.request(method, body)
  }
})

L'approche prototype est légèrement plus rapide, car ce code n'est exécuté qu'une seule fois, alors que le code constructeur est exécuté à chaque fois qu'une nouvelle instance est créée.

Un autre avantage de prototype par rapport à constructor est qu'il est compatible avec l'héritage des classes. Donc, si vous étendez votre classe plus tard, rien ne sera cassé, même si vous redéfinissez l'une de ces méthodes.

En passant, vous pouvez utiliser require('http').METHODS ou methods package au lieu du tableau codé en dur des verbes HTTP ici.

27
Leonid Beschastny

Je ne sais pas si c'est idiomatique (puisqu'il s'agit davantage de design que de langage de programmation), mais je pense personnellement que créer des fonctions explicites serait mieux:

exec_sync(...args) {
    return this.exec(true, ...args); 
}
1
zerkms

J'aime la réponse de @ leonid, mais existe-t-il un moyen d'autoriser les mutations lorsque vous utilisez des noms de propriétés calculés dynamiques.

['VERYBIGNAME', 'VERYBIGNAME2', 'VERYBIGNAME3'].forEach((method) => {
   Executor.prototype[method] = function (body) {
     return this.request(method, body)
   }
})

dans votre javascript minified et mutilé, ces chaînes VERYBIGNAME existeront. 

donc si je suis en mesure d'obtenir des références à ces fonctions VERYBIGNAME, puis-je utiliser quelque chose comme

const references = { VERYBIGNAME1, VERYBIGNAME2, VERYBIGNAME3 };

Object.assign(Executor.prototype, { ...references });
0
BoltCoder