为什么变量声明总是会覆盖函数声明?

时间:2014-01-15 14:14:03

标签: javascript function variables declaration

无论我是否在变量

之后定义函数
var a = 1;
function a() {};
typeof a // number

或者如果我在变量

之前定义函数
function a() {};
var a = 1;
typeof a // number

最终typeof结果始终为number

我在http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/

中找到了关于execution context的一些解释
Before executing the function code, create the execution context.
......
Scan the context for variable declarations:
If the variable name already exists in the variable object, do nothing and continue scanning.

但这似乎不起作用。

那我怎么解释呢?

3 个答案:

答案 0 :(得分:5)

这与JavaScript的variable hoisting有关。试试这个:

var a = 1;
var a = function() {};
typeof a // function

答案 1 :(得分:1)

你通过使用函数语句'function a(){};'隐式地多次声明变量,由于浏览器注册声明的顺序,如其他人所指出的那样提升变量并出现意外行为。

在幕后,此语句实例化一个函数对象,并将结果分配给作为函数名称传递的变量(reference),但这是在执行显式var声明之前完成的,因此会覆盖隐式宣言。如果您只是执行以下操作,它将更直观地工作:

var a = 1;
a = function(){};
console.log(typeof a);  // function

从逻辑角度来看,这是一个比其他答案中的多var声明更好的选择,因为(即使你可以),无论如何多次声明变量并不是一个好习惯。

要专门回答这个问题的“原因”:这样你就可以使用这些语句定义函数并在显式声明中使用它们,如

var a = someFunction();  
function someFunction(){ return 'someVal'; }

如果未首先解析和提升函数语句,则无法实现。

答案 2 :(得分:0)

如前所述,它与JavaScript提升的工作方式有关。需要注意的主要问题是JavaScript将完整的函数定义(以及函数体)提升到顶部,但保持变量初始化的位置(仅提升声明)。

所以如果你写这个:

var a = 1;
function a () {
}

它将被翻译为:

var a;
function a() {
}
a = 1;

如果你这样写:

function a () {
}
var a = 1;

它将被翻译为:

function a () {
}
var a;
a = 1;

所以无论你做什么,a = 1;都会保持在最底层。

请注意,理论上应该看到上述“翻译”。如果已经存在具有相同名称的函数声明,则JavaScript可能有一种省略var a;语句的方法。并且还可能存在已定义的顺序(函数在变量之前或其他方式被提升)。但所有这些都不会影响变量初始化的结果,因为变量初始化是唯一没有提升的部分。