在Javascript中制作函数的真实副本
我想在 Javascript 中定义两个函数(或类),它们具有完全相同的函数体,但它们是完全不同的对象。用例是我在主体中有一些通用逻辑,它是多态的(函数可以接受多种类型),但是通过只调用具有单一类型的函数,函数最终会更快,我假设因为 JIT 可以在每种情况下都采取更快乐的快速路径。
一种方法是简单地完全重复函数体:
function func1(x) { /* some body */ }
function func2(x) { /* some body */ }
另一种以较少重复完成相同事情的方法是eval():
function func(x) { /* some body */ }
function factory() { return eval("(" + func.toString() + ")") }
let func1 = factory(), func2 = factory()
eval()当然,缺点是任何其他工具(缩小器、优化器等)都完全出乎意料,并且有可能破坏我的代码,因此这不起作用。
在标准工具链(我使用 Typescript、esbuild 和 Vite)的范围内,是否有任何明智的方法可以做到这一点,而不使用技巧eval()或只是复制粘贴代码?我也有关于类定义的类似问题。
编辑:总结评论中发生的事情:
- 是的,性能差异是真实且可衡量的(尤其是在 Chrome 上,在 Firefox 和 Safari 上不那么明显),正如这个微基准所证明的那样。引发这个问题的真实程序要大得多,性能差异也更明显,我怀疑是因为 JIT 可以为单态函数做更多的内联,这会产生许多连锁反应。
- 返回闭包的明显解决方案不起作用,即
function factory() { function func() { /* some body */ } return func } let func1 = factory(), func2 = factory()正如第二个微基准所证明的那样。这是因为 JIT 只会编译一个函数体一次,即使它是一个闭包。
- 这可能已经是最好的解决方案,至少在标准 JS/Typescript 工具链(不包括代码生成或宏工具)中工作时如此。