代码之家  ›  专栏  ›  技术社区  ›  Myk Willis

测试变量是否已在包含范围内声明

  •  1
  • Myk Willis  · 技术社区  · 7 年前

    我有一个内部函数,它引用一个由其包含的外部函数初始化的变量:

    function outer() {
        function inner() {
          if (foo) { ... }
        }
        let foo = 'bar';
        inner();  // no error
    };
    

    但是,在某些情况下,可以调用内部函数 定义 foo 已经执行了。在这种情况下,任何对 在内部函数中导致引用错误:

    function outer() {
        function inner() {
          if (foo) { ... } // ReferenceError: foo is not defined
        }
        inner();
        let foo = 'bar';
    };
    

    考虑到这一点,这让我感到惊讶 具有块作用域,当执行内部函数时,我位于封闭块内。

    typeof 运算符-我一直认为它是测试未定义变量的安全方法-会导致相同的引用错误:

    function outer() {
        function inner() {
          if (typeof foo !== 'undefined') { ... } // ReferenceError: foo is not defined
        }
        inner();
        let foo = 'bar';
    };
    

    编辑:我现在了解到这种行为是“暂时死区”的结果 let const 变量 discussed elsewhere . 然而,我仍然在寻找一种干净、安全的方法来处理这种情况。

    是否有任何安全的方法来测试块范围变量(例如,使用“let”或“const”创建的变量)是否已达到其声明?

    2 回复  |  直到 7 年前
        1
  •  2
  •   Myk Willis    7 年前

    一种蛮力方法是简单地捕获 typeof 在“暂时死区”之前 foo 已初始化:

    function outer() {
        function inner() {
          let fooExists = false;
          try { fooExists = typeof foo !== 'undefined' } catch(e) {}
          if (fooExists) { /* ... */ }
        }
    
        inner();   // no error
        let foo = 'bar';
    }
    

    也可以使用 var 而不是 let 在函数范围内,声明将被提升到 outer ,使变量始终可用(尽管未定义):

    function outer() {
        // due to hoisting, there is a logical `var foo;` here
        function inner() {
          if (typeof foo !== 'undefined') { /* ... */ }
        }
    
        inner();   // no error; `foo` has been hoisted
        var foo = 'bar';
    }
    

    可以采取类似的方法,将 在外部功能的顶部,同时仍在使用

    function outer() {
        let foo;
        function inner() {
          if (typeof foo !== 'undefined') { /* ... */ }
        }
    
        inner();   // no error
        foo = 'bar';
    }
    

    对于问题中给出的示例,最后一个解决方案似乎是最干净的解决方案。不幸的是,在使用时不能使用它 const

        2
  •  -1
  •   Scott Marcus    7 年前
    function outer() {
        function inner() {
          if (foo) { ... } // ReferenceError: foo is not defined
        }
        inner();
        let foo = 'bar';
    };
    

    这让我很惊讶,因为foo有块作用域,而我是

    由于吊装的原因 宣言 foo 变量的类型。它执行时就像您编写了:

    function outer() {
        let foo; // declaration only, so still undefined value
        function inner() {
          if (foo) { ... } // ReferenceError: foo is not defined
        }
        inner();
        foo = 'bar'; // Not initialized until after you call inner!
    };
    

    只需在块中向上移动初始化,它就会工作:

    function outer() {
        let foo = 'bar'; // declared and initialized
        function inner() {
          if (foo) { ... } // works as expected
        }
        inner();
    };
    
    推荐文章