【问题标题】:Use Let variable declaration with With Statement将 Let 变量声明与 With 语句一起使用
【发布时间】:2019-11-14 03:50:51
【问题描述】:

我从 Ecma 规范中阅读了 with 声明,并在其中阅读了这样的声明评估。

  1. 设 val 为 Expression 的计算结果。
  2. 设 obj 是 ? ToObject(?GetValue(val))。
  3. 设 oldEnv 为正在运行的执行上下文的 LexicalEnvironment。
  4. 设 newEnv 为 NewObjectEnvironment(obj, oldEnv)。
  5. 将 newEnv 的 EnvironmentRecord 的 withEnvironment 标志设置为 true。
  6. 将正在运行的执行上下文的 LexicalEnvironment 设置为 newEnv。
  7. 令 C 为 Statement 求值的结果。
  8. 将正在运行的执行上下文的 LexicalEnvironment 设置为 oldEnv。
  9. 返回完成(UpdateEmpty(C, undefined))。

如果 with 语句使用词法环境进行评估,为什么我的示例代码不起作用?

const user = {
   fullName: "Murad Sofiyev"
};
with(user) {
    let firstName = "Tofiq";
    fullName = "Tofiq Sofiyev";
}

console.log(user.firstName); // Undefined
console.log(user.fullName); // Tofiq Sofiyev

PS:我知道 with 语句已被弃用,但这有助于我理解词法环境和变量环境:)

【问题讨论】:

    标签: javascript


    【解决方案1】:

    with(user) 之后的 { 创建了一个全新的 LexicalEnvironment。实际上在那里创建了两个环境:with'd 对象的环境和新的{ 块的环境。当您使用 let firstName = "Tofiq"; 时,您将在 inner(块作用域)环境中创建一个新变量名。

    如果您可以看到可以使用with,这可能会更明显一点没有配对的{

    const user = {
       firstName: 'foo',
    };
    with(user);
    console.log('Not a syntax error');

    在这里,由with'd 值创建的环境被创建,并且完全未被使用。 (并且没有内部环境)。

    另一个问题是对象上不存在firstName。如果对象具有firstName 属性并且您使用var 而不是let,则新的Tofiq 将被分配给该对象。

    const user = {
       firstName: 'foo',
    };
    with(user) {
        var firstName = "Tofiq";
    }
    
    console.log(user.firstName); // Tofiq
    // because var is not block-scoped
    // so `var firstName` finds an outer Lexical Environment with that same variable name

    【讨论】:

    • 你说我们声明了 2 ENV。但是我们可以从环境中为新的 { 块访问对象属性。如果有 2 个 ENV 怎么可能?
    • 因为环境相互继承(这与作用域相互继承的机制完全相同);在普通代码中,const a = 'a'; if (true) { console.log(a); } 有效,因为if 块内的环境可以看到外部环境中声明的a
    • 听起来很有趣。这意味着有创建 2 个嵌套环境:/
    • 在此之前我认为是关于对象环境记录和声明性环境记录,但你给了我其他观点。但我不知道哪个是真的)))
    【解决方案2】:

    使用let 总是在块范围内创建一个变量。因此,即使您在with 块内使用它,它也会为with 创建一个新的变量范围。如果您需要在块内进行一些计算,您可能需要这种行为。

    【讨论】:

      猜你喜欢
      • 2020-02-12
      • 2017-09-06
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-01
      相关资源
      最近更新 更多