请教一个js问题。

var a = 0;
if(true) {
    a = 1;
    function a() {};
    a = 21;
    console.log('里面' + a);
}
console.log("外面" + a);

为啥外面的a=1

阅读 518
评论
    2 个回答

    昨天看到过这个题,和我的好几个同事都研究了一番,但是没什么结论,就先把我昨天知道的给你分享一下吧。
    以下是通过打断点的方式得到的结论:

    console.log(a)
    var a = 0;
    // 此时在Stack下的Global内,出现 a 变量,值为0
    if(true) {
        console.log(a)
        // function() {}; 此时在Stack下的Block内,出现 a 变量,值为 function() {};
        // ???变量和函数声明提升,if不是函数,不会形成新的作用域,但不知道为什么函数声明提升到了这里
        a = 1;
        //此时,Block内 a = 1,Stack下的Global内 a = 0;
        function a() {};
        //此时,Block内 a = 1,Stack下的Global内 a = 1; ???这里也不明白为什么突然全局的会变成1,但通过改变 function a() {} 的位置,可以知道绝对是它的副作用。
        a = 21;
        //此时,Block内 a = 21,Stack下的Global内 a = 1;
        console.log('里面' + a);
    }
    console.log("外面" + a);
      • 9.3k

      基于 MDN function declaration ,以及上面的测试,有一个猜测:

      在例子里(见下),foo 被提升到了 if 之外,但是,在执行到 foo 的定义之前,fooundefined

      那么,其实 function foo(){return 1;} ,它会在局部作用域有一个副本,与全局的不是用一个;在执行这一语句的时候,将 local scope 的 foo 的值,赋值到了全局。

      这样考虑,可以同时解释你的例子与 MDN 的示例。

      还有就是,各个浏览器里关于局部作用域函数的实现,都跟 ECMA262 不太一样。他们是怎么实现的,如果他们自己没有放出文档的话,就只能猜了。


      var hoisted = "foo" in this;
      console.log(`'foo' name ${hoisted ? "is" : "is not"} hoisted. typeof foo is ${typeof foo}`);
      if (false) {
        function foo(){ return 1; }
      }
      
      // In Chrome: 
      // 'foo' name is hoisted. typeof foo is undefined
      // 
      var hoisted = "foo" in this;
      console.log(`'foo' name ${hoisted ? "is" : "is not"} hoisted. typeof foo is ${typeof foo}`);
      if (true) {
        function foo(){ return 1; }
      }
      
      // In Chrome: 
      // 'foo' name is hoisted. typeof foo is undefined
        撰写回答

        登录后参与交流、获取后续更新提醒