嵌套的辅助函数和性能

时间:2015-02-21 23:18:34

标签: javascript performance function

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

work(1);
work(2);

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

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

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

work(1);
work(2);

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

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

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

4 个答案:

答案 0 :(得分:6)

  

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

是的,每次致电工作

  

通常建议不要嵌套函数吗?

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

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

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
  };
}());

在封闭内的多个函数使用 log 的地方也是有意义的。

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

答案 1 :(得分:2)

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

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

每次调用外部函数都会重复此过程。

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

如果这是&#34;热&#34;函数(即多次调用)则第二种实现是无限优选的。

答案 2 :(得分:0)

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

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

如果您正在使用&#34;工作&#34;要从代码的几个部分中使用,最好将它们分开而不是嵌套它们。这使得代码更新更简单(因为您只在一个地方更新它)。

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

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

答案 3 :(得分:0)

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

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

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

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