请教一个js问题。

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

为啥外面的a=1

阅读 3.4k
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);

基于 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
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题