问题描述
首先使用定义函数的变量还是使用函数更好? 此外,摇树是否有区别?
我有很多计算(静态)密集型辅助类,我想知道最好的(内存/速度)是什么。
这里是我想到的不同方式:
class MyClass {
readonly functionA = (v: string | number,maxDeep: number,curDeep: number = 0): string => {
if (curDeep < maxDeep) {
return this.functionA(v,maxDeep,curDeep + 1);
} else {
return "function A" + v;
}
}
static functionB(v: string | number,curDeep: number = 0): string {
if (curDeep < maxDeep) {
return MyClass.functionB(v,curDeep + 1);
} else {
return "function B" + v;
}
}
functionC(v: string | number,curDeep: number = 0): string {
if (curDeep < maxDeep) {
return this.functionC(v,curDeep + 1);
} else {
return "function C" + v;
}
}
static readonly functionD = (v: string | number,curDeep: number = 0): string => {
if (curDeep < maxDeep) {
return MyClass.functionD(v,curDeep + 1);
} else {
return "function D" + v;
}
}
}
解决方法
如果您担心在这个级别优化性能,那么拥有一个只有静态方法的类会引入一些完全不必要的开销。类旨在实例化,如果您不使用该功能,就会浪费一些计算资源来使这些功能可用。
当我运行您的示例(MacOS、Chrome 90.0.4430.93)时,我得到了:
很明显,静态方法具有很大的性能成本。保证实例方法快速的地方。我希望我能告诉你原因,但我确信这与类被设计为实例化这一事实有关。
比这简单得多,是一个简单的对象。让我们添加这两个测试:
const obj = {
functionE(v,maxDeep,curDeep = 0) {
//...
},functionF: (v,curDeep = 0) => {
//...
}
};
那些运行速度与实例方法一样快。这是一种更有意义的模式。没有类,因为没有实例化。
但是还有一个更简单的选择:
function rawFunctionStatementG(v,curDeep = 0) {
//...
}
const rawFunctionVarH = (v,curDeep = 0) => {
//...
};
在性能方面,我们有一个赢家。我很确定这是因为您永远不必在对象上查找属性。您直接拥有对该函数的引用,并且可以执行它而无需询问任何其他对象首先在哪里找到它。
就摇树而言,这种形式是迄今为止最好的。捆绑器管理整个导出的值是最简单的,而不是尝试对单个对象进行切片和切块。
如果您执行以下操作:
// util-fns.ts
export function myFuncA() { /* ... */ }
export function myFuncB() { /* ... */ }
// some consumer file
import { myFuncA } from './util-fns'
然后,打包人员很容易看到 myFuncB
从未被导入或引用,并且可能会被修剪。
最后...
“真正的问题是程序员在错误的地方和错误的时间花费了太多时间来担心效率;过早优化是编程中所有邪恶(或至少大部分)的根源。” – 唐纳德·克努斯
在绝大多数 javascript 应用程序中,这种级别的性能优化不太可能产生影响。因此,根据代码库/组织的标准,使用对应用程序最有意义的数据结构。这些事情更重要。