Proper way to dynamically add functions to ES6 classes

柔情痞子 提交于 2019-12-03 19:01:07

问题


I have a simple class with a single method exec(arg1,..,argn) and I want to have a number of alias methods which call exec with predefined argument values (e.g. exec_sync = exec.bind(this, true)).

The following does the trick:

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

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

But I don't know if this is a good idea or if this is idiomatic to ES6.

UDATE:

In a real-life example I have two nested loops with respectively 3 and 4 loops, which are used to dynamically add a total number of 12 alias methods to the class. It would be a cumbersome task to explicitly define the alias methods when you actually can take advantage of JS being a prototype-based programming language.

UPDATE 2 - EXAMPLE:

Suppose we have have a simple HTTP client with a method request(method, body) and we want to provide alias methods for GET, PUT, etc. It would look something like the following:

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

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

回答1:


Your solution is fine, though it'll be better to create all those methods once on a prototype level:

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

prototype approach is slightly faster, because this code is executed only once, while constructor code is executed every time new instance is created.

Another advantage of prototype over constructor is that its compatible with classes inheritance. So, if you'll extend your class later nothing will break even if you'll redefine any of those methods.

By the way, you can use require('http').METHODS or methods package instead of hard-coded array of HTTP verbs here.




回答2:


I don't know about this being idiomatic (since it's more about design, rather than programming language itself), but I personally think creating explicit functions would be better:

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



回答3:


I like @leonid's answer, but is there a way to allow mangling when you using dynamic computed property names.

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

in your minified and mangled javascript these VERYBIGNAME strings will exist.

so if I am able to get references to these VERYBIGNAME functions can I use something like

const references = { VERYBIGNAME1, VERYBIGNAME2, VERYBIGNAME3 };

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


来源:https://stackoverflow.com/questions/32496825/proper-way-to-dynamically-add-functions-to-es6-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!