【问题标题】:execution context declared name twice?执行上下文两次声明名称?
【发布时间】:2016-07-31 16:02:15
【问题描述】:

我正在研究 Javascript 的执行上下文。但我不明白为什么“函数 foo”不会被“var foo”覆盖。 希望有人能解释一下 感谢您的回复。

函数 ace() {

console.log(typeof foo); // function pointer
console.log(typeof bar); // undefined

var foo = 'hello',
    bar = function() {
        return 'world';
    };

function foo() {
    return 'hello';
}
 var foo = 'hello';

}

王牌();

【问题讨论】:

  • foo 被覆盖

标签: javascript scope interpreter execution hoisting


【解决方案1】:

为什么“函数 foo”不会被“var foo”覆盖。

foofoo 被重新定义的那一行被覆盖

function ace() {

  console.log(typeof foo); // function pointer
  console.log(typeof bar); // undefined

  var foo = 'hello',
    bar = function() {
      return 'world';
    };

  function foo() {
    return 'hello';
  }
  var foo = 'hello';
  console.log(foo);
  try {
    foo()
  } catch(e) {
    console.log("catch:", e.message)
  }
}

ace();

【讨论】:

    【解决方案2】:

    但我不明白为什么“函数 foo”不会被“var foo”覆盖。

    var 声明不会覆盖函数声明。它们都声明了相同的变量,并且由于函数声明,它用函数初始化。只有赋值会覆盖值。

    如果你考虑到提升,你的脚本会表现得像

    function ace() {
        var foo, bar;
        var foo = function() {
            return 'hello';
        }
        var foo;
    
        console.log(typeof foo); // function
        console.log(typeof bar); // undefined
    
        foo = 'hello';
        bar = function() {
            return 'world';
        };
        console.log(typeof foo); // string
        foo = 'hello';
    }
    ace();
    

    【讨论】:

    • 感谢您的回复。但是函数不是在变量之前在激活对象上创建的吗?但是为什么“function foo”的名称会被“var foo”覆盖?对不起,我试图理解它
    • @Overste:函数不是特殊类型的变量。函数声明只是声明一个变量并使用函数对象对其进行初始化。变量声明只是声明了同一个变量,除非它已经存在,否则用undefined 对其进行初始化。 function foovar foo覆盖-foofoo = …覆盖。
    • 感谢您的回复。我想我明白了,谢谢。但是我有最后一个问题:我读过他说的文章:即使 foo 被声明了两次,我们从创建阶段就知道函数是在变量之前在内存中创建的。是不是: var foo = function() { return 'hello'; } 而不是 var foo, bar;
    • @Overste 重点是没关系。实际上the spec says函数最终被初始化,但实际上它们都是相同类型的绑定(变量),并且都是一次创建的。