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
Proper way to dynamically add functions to ES6 classes
提问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 exec
with 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)
,我们希望提供别名方法GET
,PUT
等等。它看起来像下面这样:
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 prototype
level:
您的解决方案很好,但最好在一个prototype
级别上创建所有这些方法:
['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.
prototype
方法稍微快一点,因为这段代码只执行一次,而每次创建新实例时都会执行构造函数代码。
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.
prototype
over 的另一个优点constructor
是它与类继承兼容。因此,如果您稍后扩展您的类,即使您重新定义这些方法中的任何一个也不会中断。
By the way, you can use require('http').METHODS
or methods
packageinstead of hard-coded array of HTTP verbs here.
顺便说一句,您可以在此处使用require('http').METHODS
或methods
打包而不是硬编码的 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 });