将函数动态添加到 ES6 类的正确方法
Posted
技术标签:
【中文标题】将函数动态添加到 ES6 类的正确方法【英文标题】:Proper way to dynamically add functions to ES6 classes 【发布时间】:2015-12-06 10:36:55 【问题描述】:我有一个带有单个方法 exec(arg1,..,argn)
的简单类,并且我想要一些别名方法,它们使用预定义的参数值(例如 exec_sync = exec.bind(this, true)
)调用 exec
。
以下方法可以解决问题:
class Executor
constructor()
this.exec_sync = this.exec.bind(this, true);
exec(sync, cmd, args/* ... */)
// impl
但是我不知道这是否是个好主意,或者这是否符合 ES6 的习惯。
更新日期:
在一个真实的例子中,我有两个嵌套循环,分别有 3 个和 4 个循环,用于向类动态添加总共 12 个别名方法。当您实际上可以利用 JS 作为基于原型的编程语言时,显式定义别名方法将是一项繁琐的任务。
更新 2 - 示例:
假设我们有一个简单的 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
【问题讨论】:
为什么不显式地创建多个函数?exec_sync(...args) return this.exec(true, ...args);
@zerkms 我认为这会更清楚类的作用。我只是对做类似事情的可能性感兴趣。
ES6 类只是语法糖。在运行时向对象添加属性方面没有任何改变。
【参考方案1】:
您的解决方案很好,但最好在 prototype
级别创建一次所有这些方法:
['GET', 'PUT', 'POST', 'DEL'].forEach((method) =>
Executor.prototype[method] = function (body)
return this.request(method, body)
)
prototype
方法稍微快一些,因为这段代码只执行一次,而构造函数代码是每次创建新实例时执行的。
prototype
相对于constructor
的另一个优势是它与类继承兼容。因此,如果您稍后扩展您的类,即使您重新定义这些方法中的任何一个,也不会出现任何问题。
顺便说一句,您可以在此处使用require('http').METHODS
或methods
package 代替HTTP 动词的硬编码数组。
【讨论】:
谢谢。 http的东西应该是一个例子,我没有在我的代码中使用它:) 让我们continue this discussion in chat.【参考方案2】:我不知道这是惯用的(因为它更多的是关于设计,而不是编程语言本身),但我个人认为创建显式函数会更好:
exec_sync(...args)
return this.exec(true, ...args);
【讨论】:
在一个真实的例子中,我有 2 个嵌套循环,它们分别有 3 个和 4 个项目,用于将总共 12 个项目动态添加到类中。手动添加所有内容会有点麻烦。 @YanFoto 我会考虑把它移到一个单独的类中。 那些方法实际上和语义上属于类。如果我将它们移到一个单独的类中,我仍然需要明确定义它们。还是我在这里遗漏了什么? @YanFoto 那些只是辅助包装器。但同样,这是设计中的品味或偏好问题。对此没有单一的客观答案。 感谢您的帮助。我举了一个例子,在一定程度上说明了这种情况。我想避免下一个开发人员将我的代码视为 ugly :D【参考方案3】:我喜欢@leonid 的回答,但是当您使用动态计算属性名称时,有没有办法允许修改。
['VERYBIGNAME', 'VERYBIGNAME2', 'VERYBIGNAME3'].forEach((method) =>
Executor.prototype[method] = function (body)
return this.request(method, body)
)
在您缩小和损坏的 javascript 中,这些 VERYBIGNAME 字符串将存在。
所以如果我能够获得对这些 VERYBIGNAME 函数的引用,我可以使用类似的东西
const references = VERYBIGNAME1, VERYBIGNAME2, VERYBIGNAME3 ;
Object.assign(Executor.prototype, ...references );
【讨论】:
以上是关于将函数动态添加到 ES6 类的正确方法的主要内容,如果未能解决你的问题,请参考以下文章