【问题标题】:Does JavaScript automatically skip empty/bodiless functions?JavaScript 会自动跳过空/无实体函数吗?
【发布时间】:2019-06-18 14:21:11
【问题描述】:

包括“tl;dr”

当尝试禁用日志记录以避免部署垃圾邮件时,我曾经做过类似的事情

if (isDebug)
    console.log(...);

但我觉得(或在线阅读)这会减慢代码的整体速度,因为每次都会评估条件(我通常包括很多这些,并且经常通过循环、setIntervals 或 w 调用函数/e)。

因此,我现在切换到使用自定义记录器(如

)简单地“清空”函数
function LOGGER_MODULE_FACTORY() {
  let current_log_level = "log";
  return {
    log: console.log,
    info: console.info,
    warn: console.warn,
    error: console.error,
    setDebug: function(logLevel) {
      current_log_level = logLevel;
      this.log = (logLevel === true || logLevel === "log") ? console.log : function () {};
      this.info = (logLevel === true || logLevel === "log" || logLevel === "info") ? console.info : function () {};
      this.warn = (logLevel === true  || logLevel === "log" || logLevel === "info" || logLevel === "warn") ? console.warn : function () {};
      this.error = (!logLevel) ? function () {} : console.error;
      return logLevel;
    },
    getCurrent_log_level: function () { return current_log_level; }
  }
}

认为运行一个空函数可能比评估一个表达式更快,而且写起来感觉更干净。

我尝试创建一个 fiddle 来测试我的理论并比较性能,但这些值通常非常随机......

编辑jsperf test 有趣的结果。 "Chrome 64" 的结果来自在 Edge 上运行。

我的推理依赖于这样一个事实,即我很少阅读有关 CPU 的内容,并且显然,它们自己做事是为了优化一般运行时,例如,跳过无用的操作:假设我们有:

a = x
b = y
c = a + 3

CPU 实际上会忽略第二行(或其他什么……我远非专家啊,我只是好奇地读到了这个事实)。

现在,由于我们在浏览器上可能会在某个时候使用控制台访问任何全局声明的变量,所以这不可能发生,所以我觉得我应该简单地在线询问:

tl;博士:

重复调用空/无实体函数(我创建的页面基本上 24/7 在仪表板上运行)在性能方面是否比在原始函数前面放置条件更好 (console.log / info / warn / error)?

基本上,您是在问哪个更快 f = () => {}; f() 或标志 = 假; if (flag) f()

【问题讨论】:

  • “我觉得……”“可能是……”——你有没有做过一些实际的测量,这是否是一个问题一开始就解决了?
  • 不仅是 CPU 优化,还有 JavaScript 引擎优化——它们很容易跳过整个块。不过,我想说的是,如果每次登录时对日志级别进行检查确实会对性能产生不利影响(因为它们太多了),那么你需要阅读的日志太多,以至于它们实际上毫无用处。跨度>
  • 这真的是瓶颈吗?从技术上讲,一个空函数应该比一个具有将被评估并确定函数是否运行的条件的函数运行得更快。但是,我希望浏览器能够优化差异。尽管如此,直接替换函数而不是将每个调用隐藏在标志后面应该更容易维护。
  • 取决于你的 JS 引擎是更擅长内联小函数调用(包括空函数调用)还是内联常量到分支条件。
  • 使用 jsperf.com 来执行 JavaScript 基准测试,而不是 jsfiddle.com。

标签: javascript function if-statement optimization


【解决方案1】:

isDebug 不会在每次执行时都被评估,但只会读取存储的变量。

如果是if (isDebug())就不一样了,这种情况下,解析器每次遇到语句,都会对函数求值。

显然,读取isDebug 布尔变量会增加一些开销,但这是无法察觉的,因为读取和处理变量是编程语言的主要目的,因此读取布尔变量所需的时间总是低于任何代码中的其他语句。

重新分配 console.log 函数不是一个坏主意,它可能有助于一次性启用或禁用日志。但这是针对不同问题的解决方案

【讨论】:

  • 根据 cmets 的说法,似乎没有明确的答案,因为它可能因一个 JS 引擎到另一个和/或浏览器而异,总的来说,无论如何可能影响不大。尽管您提到“将仅读取存储的变量”让我认为,与其让一个模块调用控制台函数,我可以立即更改控制台的原型并在那里进行标志检查。但是随后每次都会调用该函数(已评估,我认为),这可能是最糟糕的老板世界啊啊啊无论如何,我想我的问题很糟糕/太依赖环境了。
  • @DixiPoowa 重新分配console.log 函数不需要评估调试模式。这是仅在应用程序引导时进行的操作。而且我有足够的信心说答案是确定的:延迟如此之小,根本不重要
猜你喜欢
  • 1970-01-01
  • 2011-11-06
  • 2016-06-01
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
  • 2019-05-13
  • 2015-12-07
相关资源
最近更新 更多