With 语句的性能影响

Performance Implications of With Statements

好的,所以,在过去的四十八小时里,我已经看到足够多的人提到这个问题了,所以我需要把它作为一个问题来问。在“JavaScript for Professional Web Developers" (2012) it says the same thing as it does on MDN:

Use of the with statement is not recommended, as it may be the source of confusing bugs and compatibility issues.

但是,Zakas 的书中还指出(没有进一步的实质性阐述)“[出于性能原因,不应使用它们]”。这个问题显然是 "bad enough" 在 Strict 模式下,ECMAScript 不允许 with 语句。

这真的是出于性能原因吗?还是因为人们受不了?

如果实际上部分原因是性能,它们如何以及为什么会对性能产生负面影响?

with 语句的问题都源于同一个问题:当使用 with 时,作用域变得复杂

考虑以下示例:

with (foo) {
    with (bar) {
        return x;
    }
}

这看起来很简单,但实际上可以有各种可能的结果。

  1. 如果 foo 被定义为 and 它有一个 属性 叫做 bar and bar 有一个名为 x 的 属性,然后返回 foo.bar.x
  2. 如果 foo 未定义,但 bar 已定义,并且它有一个名为 x 的 属性,则返回 bar.x
  3. 如果定义了 foo 但它没有 属性 调用 bar,则使用 window 查找检索 bar

不胜枚举。所以该行为有各种可能性,所有这些都是脆弱的,因此可能存在错误,但为什么这是一个 性能 问题?

好吧,考虑一下:

return foo.bar.x;

没有任何 with 语句,这对于 JavaScript 引擎来说很容易优化。范围内是否有一个名为 foo 的变量(使用 var 声明)?如果是这样,请使用它。如果不是,请执行 window 查找。这几乎可以静态确定。

使用 with 时,每个变量查找 都需要在运行时动态确定。如果您指的是 with 块内的全局变量,引擎仍然必须检查 属性 是否存在于与 with 一起使用的对象上。如果嵌套 with 个块,情况会变得更糟。

使用 with 会使行为变得如此复杂,以至于在大多数情况下,JavaScript 优化器只会放弃,因为它抛出了 window 的大量编译时保证。 当范围是动态确定的,而不是词法确定时,就很难推理了。

所以,是的,这是使用 with 不是一个好主意的另一个原因。不惜一切代价避免它。