【问题标题】:What is the difference between a let block statement and an equivalent with statement?let 块语句和等价的 with 语句有什么区别?
【发布时间】:2011-09-23 00:02:28
【问题描述】:

已过时

let 语句的块版本在最终确定之前已从 ES6 中删除,并且已从支持它的浏览器中删除。这个问题现在只具有历史意义。

使用 ECMAScript 6 let block statement 和使用带有等效对象字面量的 with 语句之间有什么区别吗?

使用let 语句

var x = 10;
let (x = x * 10,
     y = x + 5) {
    console.log("x is " + x + ", y is " + y);
}

使用with 语句

var x = 10;
with ({x: x * 10,
       y: x + 5}) {
    console.log("x is " + x + ", y is " + y);
    // writes "x is 100, y is 15"
}

【问题讨论】:

  • 这个问题是为了娱乐,还是您正在认真考虑使用with 进行范围界定?
  • 如果答案最终是“没有区别”,那么我会考虑,但我主要是好奇,因为我预计会有区别,但找不到。

标签: javascript language-features with-statement let ecmascript-6


【解决方案1】:

您可以同时使用withlet 语句来实现相同的目标,但我在这里看到了两个显着差异。最后,let 语句是with 语句的新版本,去掉了后者的缺点。

性能:在with 语句的情况下,您将额外的JavaScript 对象添加到作用域链中。这不是一个小成本,您必须记住对象可能有一个很长的原型链,因此要查找变量,JavaScript 引擎首先必须搜索对象及其所有原型。另一方面,对于let 语句,引擎最多只需要搜索一个附加对象。 let 语句确实可以在没有任何开销的情况下实现,因为在 let 语句中声明的所有变量在编译时都是已知的,并且 JavaScript 引擎可以轻松优化代码,例如通过基本上将您的示例视为:

var x = 10;
var let1x = x * 10;
var let1y = x + 5;
{
    console.log("x is " + let1x + ", y is " + let1y);
}

代码可读性:正如上面已经提到的,let 语句总是使所有声明在编译时可见,这可以防止这样的代码:

with (foo)
{
    console.log("x is " + x + ", y is " + y);
}

如果你看上面的代码,x 是什么,y 是什么?它们是对象foo 的函数变量或属性吗?如果不知道foo 是什么,你就无法说出它——而且对于同一函数的不同调用,它可能会有所不同。这是 with 声明已被弃用的主要原因。虽然您可以按照您在问题中所做的方式使用它(这很好),但它也允许非常有问题和不可读的代码结构。 let 声明没有 - 灵活性较低有时是一个优势。

【讨论】:

    【解决方案2】:

    我能想到的最好的办法是with 也会泄漏Object 原型的任何属性:

    with ({x: 10}) {
        hasOwnProperty = 3;
        console.log(hasOwnProperty);  // 3
    }
    console.log(hasOwnProperty);  // [native code]; this is window.hasOwnProperty
    

    在实践中不太可能成为问题,但仍然是一个潜在的问题。

    我还怀疑with 比词法稍慢,因为它添加了另一个必须搜索的命名空间。

    老实说,我只是避免这两种结构; with 风格的隐式属性访问不适合我,如果我真的需要像这样的紧凑范围,那么带有 let 表达式的裸块比 let 块读起来更尴尬。

    【讨论】:

    • 请注意,ECMAScript 5 允许我们创建一个没有原型的对象 Object.create(null),因此实际上使用它似乎没有副作用。但是,ES5 的严格模式禁用了with,所以这只能在 ES5 的默认模式下实现,在 ES6 中是不可能的。
    • 请参阅Was there a way to create an object without a prototype prior to ES5? 了解 ES3 的可能(尽管非常不切实际)替代方案。
    【解决方案3】:

    以下是每个语句的不同范围规则。

    与:

    with 语句使对命名引用的访问效率低下,因为这种访问的范围直到运行时才能计算出来

    让:

    使用 let 定义的变量的范围是 let 块本身,以及包含在其中的任何内部块,除非这些块以相同的名称定义变量。

    let 语句是非标准的,而with 语句在严格模式下不可用。

    参考文献

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-22
      • 1970-01-01
      • 1970-01-01
      • 2012-09-30
      • 2014-05-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多