繁体   English   中英

嵌套的辅助函数和性能

[英]Nested helper functions and performance

嵌套的辅助函数可以使您的代码更易于理解。 Google甚至建议在其样式指南中使用嵌套函数。 我想知道这些嵌套函数和性能的实例化。 例如,

work(1);
work(2);

function work(a) {
    // do some stuff
    log();
    // do some more stuff
    function log() {
        console.log(a);
    }
}

work实例化一次,但是log实例化两次?

如果每次执行work都会实例化log ,那么通常建议不要嵌套函数吗? 相反,编写如下代码

work(1);
work(2);

function work(a) {
    // do some stuff
    log(a);
    // do some more stuff
}

function log(a) {
    console.log(a);
}

这些例子过于简单,问题更多的是一般情况。

工作实例化一次,但是日志实例化两次?

是的,每次打电话都要工作

通常建议不要嵌套功能吗?

为什么不? 我认为你暗示了性能问题。

练习是好还是坏取决于你使用它的原因。 在简单的帮助器的情况下,最好将它们保持在本地,因为这意味着您可以使它们适合您的特殊情况,而不用担心一般功能的额外缺点。 例如,填充前导零的数字:

function pad(n) {
  return (n<10? '0' : '') + n; 
}

作为一个辅助工作非常好,其中n预计总是在0到99的范围内,但是作为一般函数缺少很多功能(处理非数字n,-ve数等)。

如果您担心性能,可以始终使用闭包,这样助手只会实例化一次:

var work = (function() {

  function log() {
    console.log(a);
  }

  return function (a) {
    // do some stuff
    log();
    // do some more stuff
  };
}());

在闭包内多个函数使用日志的情况下,这也是有意义的。

请注意,对于单个案例,这非常微观优化,并且不太可能在性能上产生任何明显的差异。

实例化嵌套的函数对象,并将其添加到运行封闭函数时创建的LexicalEnvironment 这些嵌套函数中的每一个都将在它们上创建[[Scope]]属性。 此外,当运行嵌套函数时,将创建一个新的LexicalEnvironment对象,并将[[Scope]]复制到其outer属性。

当封闭函数完成时,嵌套的函数对象及其相关的内存将有资格进行垃圾回收。

对于外部函数的每次调用,此过程都将重复此过程。

将此与第二个实现进行对比,其中函数对象只需创建一次; 同样它的垃圾收集。

如果这是“热”函数(即多次调用),那么第二种实现是无限优选的。

RobG是对的。 性能我们受每个工作线程的实例化函数的影响。 它是否是一个明显的问题实际上归结为你有多少同时活动的工作线程,因为这会影响内存消耗和执行速度。

如果性能是您的应用程序的一个大问题(例如,复杂,繁重的功能),并且您只想在一个地方使用该功能,那么闭包是可行的方法。

如果您从“工作”调用的函数是从代码的几个部分使用的,那么最好将它们分开而不是嵌套它们。 这使得代码更新更简单(因为您只在一个地方更新它)。

大多数JS引擎只解析一次代码(即使对于嵌套函数),因此实例化函数所涉及的工作不是一个大问题。

另一方面,如果您有许多嵌套级别以及多个同时线程或事件侦听器,则内存使用可能会成为问题,因此在这些情况下(在大型应用程序中)应仔细管理嵌套。

是。 每次调用嵌套函数时都会发生实例化。 实例化函数确实使用CPU时间,但它不像解析那么重要。

因此,对于一般情况(不是现在你提到你的函数每秒会被调用多次),解析时间比实例化更有意义。

在这种情况下,嵌套函数将使用大量的内存和CPU时间,CSO最好使用RobG的解决方案(闭包),其中函数被实例化一次并且它们被简单地调用,从而导致更少的内存使用。

如果您希望在这段关键代码中使用更多优化代码,则应尽量使用尽可能少的函数,因为这样可以更快地工作,尽管代价是丢失代码可读性和可维护性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM