javascript 向 ES6 类动态添加函数的正确方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32496825/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 15:22:37  来源:igfitidea点击:

Proper way to dynamically add functions to ES6 classes

javascriptecmascript-6idiomatic

提问by Yan Foto

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

我有一个带有单个方法的简单类,exec(arg1,..,argn)我想要一些别名方法,这些方法exec使用预定义的参数值(例如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
  }
}

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

我不知道这是否是一个好主意,或者这是否符合 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.

在一个真实的例子中,我有两个嵌套循环,分别有 3 个和 4 个循环,它们用于向类动态添加总共 12 个别名方法。当您实际上可以利用 JS 作为基于原型的编程语言时,显式定义别名方法将是一项繁琐的任务。

UPDATE 2 - EXAMPLE:

更新 2 - 示例:

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:

假设我们有有一个方法,一个简单的HTTP客户端request(method, body),我们希望提供别名方法GETPUT等等。它看起来像下面这样:

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

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

回答by Leonid Beschastny

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

您的解决方案很好,但最好在一个prototype级别上创建所有这些方法:

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

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

prototype方法稍微快一点,因为这段代码只执行一次,而每次创建新实例时都会执行构造函数代码。

Another advantage of prototypeover constructoris 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.

prototypeover 的另一个优点constructor是它与类继承兼容。因此,如果您稍后扩展您的类,即使您重新定义这些方法中的任何一个也不会中断。

By the way, you can use require('http').METHODSor methodspackageinstead of hard-coded array of HTTP verbs here.

顺便说一句,您可以在此处使用require('http').METHODSmethods打包而不是硬编码的 HTTP 动词数组。

回答by zerkms

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); 
}

回答by BoltCoder

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

我喜欢@leonid 的回答,但是当您使用动态计算属性名称时,有没有办法允许修改。

['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.

在您缩小和损坏的 javascript 中,这些 VERYBIGNAME 字符串将存在。

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

所以如果我能够获得对这些 VERYBIGNAME 函数的引用,我可以使用类似的东西

const references = { VERYBIGNAME1, VERYBIGNAME2, VERYBIGNAME3 };

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