【问题标题】:JavaScript 'hoisting' [duplicate]JavaScript“提升”[重复]
【发布时间】:2013-02-25 00:15:14
【问题描述】:

我遇到了 JavaScript 'hoisting',但我没有弄清楚这段 sn-p 代码的真正作用:

var a = 1;

function b() {
    a = 10;
    return;

    function a() {}
}

b();
alert(a);

我知道像 (function a() {}) 这样的函数声明将被提升到函数 b 范围的顶部,但它不应该覆盖 a 的值(因为函数声明会覆盖变量声明而不是变量初始化)所以我希望警报的值是 10 而不是 1!!

【问题讨论】:

标签: javascript hoisting


【解决方案1】:
  1. 全局a 设置为1
  2. b() 被调用
  3. function a() {} 被提升并创建一个 local 变量 a 来掩盖全局 a
  4. 本地a设置为10(覆盖函数a
  5. 全球a(仍为1)收到警报

【讨论】:

  • 谢谢@Quentin 我错过了事实 3(该函数 a() {} 创建了一个掩盖全局 a 的局部变量)
  • @Quentin:你能用代码展示一下这个函数在提升后的样子吗?
  • @Brown_Dynamite — 看起来像问题中的内容。它按此答案中描述的顺序运行。
  • 那么如果a没有被提升,调用函数b()会全局设置a = 10,那么alert(a)会输出10?如果我理解正确?
  • 理解提升的最好方法是像编译器那样说话,Grate
【解决方案2】:

这是因为此示例中的编译/解释顺序有些误导。 function a () {} 行在函数的任何其余部分执行之前被解释,所以在函数的最开始,a 的值是function a () {}。当您将其重新分配给10 时,您将在函数b() 的本地范围内重新分配a 的值,然后在您返回时将其丢弃,而将a = 1 的原始值留在全局范围内。

您可以通过在适当的位置放置alert()s 等来验证这一点,以查看a 在各个点的值。

【讨论】:

    【解决方案3】:

    (1) JavaScript 没有块语句作用域;相反,它将是块所在的代码本地的。

    (2) Javascript 在函数范围内声明变量,这意味着在函数中声明的变量在该函数的任何位置都可用,甚至在它们被赋值之前 .

    (3) 在函数体内,局部变量优先于同名的全局变量。 如果你声明一个与全局变量同名的局部变量或函数参数,你实际上隐藏了全局变量

    你的代码是一样的:(阅读评论

    <script>
    var a = 1;          //global a = 1
    function b() {
        a = 10;         
        var a = 20;     //local a = 20
    }
    b();
    alert(a);           //global a  = 1
    </script>
    

    参考:
    (1)JavaScript Variable Scope:
    (2)A Dangerous Example of Javascript Hoisting
    (3)Variable scope

    所以在你的代码中:

    var a = 1;          //global a = 1  
    function b() {
        a = 10;         
        return;
        function a() {} //local 
    }
    b();
    alert(a);           //global a = 1  
    

    【讨论】:

    • 你在哪里写了“local a Undefined”——这实际上不是真的。函数声明在父范围的任何内容之前解析,因此在这种情况下,当您分配 a = 10 时,您已经用值 10 覆盖了函数 a() {}。请参阅 Quentin 的回答
    • @rochal 不,请阅读这篇文章Javascript hoisting can be especially nefarious in loops 还要检查 safari 浏览器上的代码...让我知道是的,大多数浏览器上的 a=10 ..实际上未定义的行为不是错误
    • 从昆汀的回答中阅读第 4 点。此时a 已经存在——它是一个函数,而不是未定义的。 Safari 与 Chrome 有什么不同?
    • @rochal variables declared in a function are available anywhere in that function, even before they are assigned a value 我也检查了它,并给了10 但是根据三个教程(我给出了链接)它应该是未定义的,10 是因为不明确的。 Quentin 根据输出回答,但我认为某些浏览器可能不是 10..
    • 再一次,在您的示例代码中:a = 10; //local a Undefined is incorrect a = 10; //local a is function(){} 是正确的,因为一旦您检查内部函数 b() 的值,它就已经已被本地函数 a(){} 覆盖,因此您对“local a Undefined”的评论无效。和浏览器无关,是语言特性。
    【解决方案4】:

    当我读到你写的同一篇文章JavaScript Scoping and Hoisting 时,我也很困惑,因为作者从未展示过编译器中两个开始示例代码的解释。

    这是您提供的示例,页面上的第二个示例:

    var a = 1;
    function b() {
        function a() {} // declares 'a' as a function, which is always local
        a = 10;
        return;
    }
    b();
    alert(a);
    

    这是页面上的第一个示例:

    var foo = 1;
    function bar() {
        var foo; // a new local 'foo' variable
        if (!foo) {
            foo = 10;
        }
        alert(foo);
    }
    bar();
    

    希望对你有帮助

    【讨论】:

    【解决方案5】:
    1. 函数声明function a(){}首先被提升,因此在本地范围内创建a
    2. 如果您有两个同名变量(一个在全局另一个在本地),则局部变量总是优先于全局变量。
    3. 当您设置a=10 时,您设置的是局部变量a,而不是全局变量。

    因此,全局变量的值保持不变,你会得到,alerted 1

    【讨论】:

      猜你喜欢
      • 2014-05-17
      • 2017-01-08
      • 2016-04-05
      • 1970-01-01
      • 2019-05-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      • 2018-06-10
      相关资源
      最近更新 更多