假设我们有一个像这样的功能:
function foo() {
// do some work...
return () => {}; // foo returns a function
}
客户端代码可以在两种情况下使用foo
:
const result = foo();
// some code that uses result...
foo();
我想知道运行时(我不想引用语言本身,因为这很可能依赖于实现)是否会优化第一种情况,所以我不必自己这样做:
function foo(needTheResultValue = false) {
// do some work...
if (needTheResultValue) return () => {};
// nothing is returned if the caller didn't ask for it
}
V8开发人员在这里。简短的答案是“这取决于您,不用担心”。
[一般来说,V8(据我所知,还有其他引擎)是基于每个功能进行优化的。因此,在您的示例中,如果foo
被优化时,它不知道将使用还是忽略其返回值,因此无法优化它。
例外是内联:当优化调用函数时,优化编译器具有内联被调用函数的能力,例如在此示例中:
function foo() {
// Do some FOO work...
return {};
}
function bar() {
foo();
// Do some BAR work...
}
foo
被优化后,它将(继续)返回一个新分配的空对象,而不管从何处调用它。当优化bar
时,编译器可能会决定内联foo
,并在此步骤后看到(它自己的假设函数的内部表示,例如):
function bar() {
// Do some FOO work...
{};
// Do some BAR work...
}
然后它可以轻松地将未使用的对象分配放在那里。
就是说,正如对该问题的评论所指出的那样,您不必担心这一点。 (除非您碰巧不必要地花费大量时间来构建昂贵但未使用的返回值-但这似乎不太可能,因为这是相当低效的,因此您一开始就不会编写这样的代码。)
特别是,返回任何您已经计算出的值与不返回任何东西相比,其成本为[[zero,因为每个函数总是返回某些东西-如果它没有return
语句,那么引擎将安静地运行为您插入一个return undefined;
。这意味着function f1() {}
和function f2() { return undefined; }
将编译为完全相同的代码。如果您决定编写类似的内容:
function overly_clever(need_result) {
let result = do_some_work();
if (result < 0) handle_error();
if (need_result) {
return result;
} else {
// Return nothing.
}
}
然后,该功能将比用简单的return result
替换空行之后的所有内容的效果略微(无法测量)slower,因为“空”
因此,简而言之:不用担心。编写有意义的代码,让引擎负责对其进行优化。else
分支(自动插入了它)return undefined;
不比return result
快,因此评估need_result
条件是浪费时间。(为了完整性:如果您确实需要进行手动优化工作,请通过以下方法进行指导:对您的应用程序进行配置,以查看花了最多时间的地方,并评估任何尝试的更改的效果,以查看它们是否有效有效。请勿使用微基准,因为它们容易引起误解。)