【问题标题】:Difference between codes of lexical scope词法范围代码之间的区别
【发布时间】:2020-06-25 10:12:02
【问题描述】:

我想知道下面两段代码的区别:

function foo() {
    var a = 'private variable';
    return function a(){
        console.log(a) 
    }
}
foo()(); // output: function a(){...}

function foo() {
    var a = 'private variable';
    function a(){};
    return () => {console.log(a)} 
}
foo()(); // output: private variable

在第一个代码块中,根据提升,函数定义应该被提升,然后var a = 'private variable'重写a,但是为什么console.log(a)输出函数定义?

【问题讨论】:

标签: javascript lexical-scope


【解决方案1】:

这不是关于提升。第一个变体实际上并没有声明一个函数,它只是一个函数表达式(即一个“lambda”或一个“闭包”),它没有在它自己的词法范围内声明任何东西。 'a' 在该表达式中所做的是分配结果函数对象的 'name' 属性,并使其可用于其主体的词法范围:

例如在节点中:

> const f = function a() {console.log(a);}
undefined
> a
Thrown:
ReferenceError: a is not defined
> f
[Function: a]
> f()
[Function: a]
undefined

另见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function

【讨论】:

    【解决方案2】:

    我希望下面的代码可以帮助您了解正在发生的事情。

    当您使用return function a() { ... } 时,它不会被视为function declaration,而是会像a = function () { ... }; return a; 一样被视为Variable assignment。并且return 将在稍后执行a 将保持值为function

    如以下代码所示,您可以确保在到达该行之前进行分配。因此,当我们使用foo(1)(); 时,它会输出private variable

    function foo(returnString) {
      var a = 'private variable';
      if (returnString)
        return function() { console.log(a); };
      return function a() { console.log(a); };
    }
    foo()(); // output: function a() { console.log(a); }
    foo(1)(); // output: private variable

    在您的第二种情况下,它非常简单。根据Order of precedence

    1. 变量赋值优先于函数声明
    2. 函数声明优先于变量声明

    function foo() {
      var a = 'private variable';
      function a() {};
      return () => { console.log(a); }
    }
    foo()(); // output: private variable

    【讨论】:

      【解决方案3】:

      在第一种情况下,当您在 console.log 中引用 a 时,您实际上是在引用函数 a,它已经覆盖在 var = a 上,因此您无权访问它。

      在第二个选项中,function a() {} 实际上移动到 var a = 'private variable' 上方,因此代码如下所示:

      function a() {};
      var a;
      a = 'private variable';
      

      这就是为什么当您调用 foo()() 时,您的 var a = 'private variable'; 会覆盖函数 a 并且您会在终端中看到 private variable

      【讨论】:

        猜你喜欢
        • 2021-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-23
        • 2016-06-11
        • 2015-12-13
        • 2015-10-09
        • 1970-01-01
        相关资源
        最近更新 更多