How to dynamically generate class method names in an es6 class?

1.4k Views Asked by At

I am trying to figure out if it’s possible to generate method names on an es6 class. Take for example the following example, a Replacer, which runs replacement rules from a ruleset:

let smileyRules = [
  { ascii: ':)',  unicode: ' ' },
  { ascii: '8)',  unicode: ' ' }
]

class Replacer {
  constructor(rules){
    this.rules = rules
  }

  replace(text, from, to){
    this.rules.forEach(rule => text = text.replace(rule[from], rule[to])) 
    return text
  }
}

let smileyizer = new Replacer(smileyRules)

smileyizer.replace(':)', 'ascii', 'unicode')
// " "

smileyizer.replace(':)', 'unicode', 'ascii')
// ":)"

So that does what it’s supposed to, but I would also like to generate convenience methods that would work like this:

smileyizer.ascii2unicode(':)')

which would internally call

smileyizer.replace(':)', 'ascii', 'unicode')

Of course, I would want to enable unicode2ascii as well. (And in fact, the point of this whole thing is that it will be used with rulesets where each rule has perhaps a dozen keys, so that's a lot of convenience methods.)

In my Replacer class, I expect to generate the methods with something akin to:

generate(){
  this.rules.map(firstRule =>
    this.rules.map(secondRule => {
      // somehow create method called firstRule + '2' + secondRule 
    })
  }
}

…and then I would call this from the constructor.

I know it’s possible to create computed properties using bracket notation, but I can't figure out how I would do something equivalent from inside another method.

Solution (thanks @DShook)

Here’s a working generate method:

  generate(){
    let names = Object.keys(this.rules[0])
    names.forEach(firstName =>
      names.forEach(secondName => {
        let method = firstName + '2' + secondName
        this[method] = (text, from, to) => this.replace(text, firstName, secondName)
      })
    )
  }
2

There are 2 best solutions below

1
On BEST ANSWER

In your constructor you would just need to dynamically create the functions however you need to like this:

this['firstRule' + '2' + 'secondRule'] = function(text, from, to){
  return text;
}
2
On
generate(){
  this.rules.map(firstRule =>
    this.rules.map(secondRule => {
       this[firstRule+"2"+secondRule] = char => this.replace(char, firstRule, secondRule);
    });
  );
}

However, dynamic methods are a very bad idea...