函数声明和声明变量同时存在,提升的规则是什么?

我们知道声明变量是会提升的:

var a = 1;
//上面一行相当于下面这样:
var a;
a = 1;

同时,函数声明也是会被提升的:

foo();
function foo(){};
//上面两行相当于下面这样:
var foo;
foo = function (){};
foo()

那么,变量和函数声明都有时,谁会提升到更上面呢?怎么排序呢?比如下面这样:

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

是这样吗?

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

因为在《你不知道的JAVASCRIPT》看到这句话,有点困惑:

函数声明和变量声明都会被提升。但是一个值得注意的细节是,函数会首先被提升,然后才是变量。函数声明会被提升到普通变量之前。

所以说会是这样排序吗:

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

求解排序规则,谢谢!

阅读 4.2k
3 个回答

首先,我们可以把它分为4块内容

var a ;
a =1;
foo();
function foo();

我们想知道提升后排序是什么形式?
目前已知条件是,变量声明会提升到变量赋值之前,所以我们可以先将变量声明放到前两位,暂时不管其内部顺序:

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

接下来我们来分别确定声明和赋值模块的内部排序。
为了进行实验,我们对foo函数进行扩充,所以现在的排序为:

var a;
function foo(){console.log(a+1)};
a=1;
foo();

先不要管为什么这么改,我们继续实验,实验过程中会理解。
为了便于理解,实验分两次进行。
首先:我们对变量声明模块进行实验。

var a=1;
console.log(foo);//若输出为function foo(){}则证明函数声明位于变量声明之前;若为undefined,说明相反。
foo();
function foo(){console.log(a+1)};

然后:我们对变量赋值模块进行实验。

var a=1;
foo();//若输出为undefined1,则证明foo()在a=1之前;若输出为2,则说明a=1在foo()之前。
function foo(){console.log(a+1)};

下面来进行实验:

var a=1;
console.log(foo);//若输出为function foo(){}则证明函数声明位于变量声明之前;若为undefined,说明相反。
foo();
function foo(){console.log(a+1)};

VM1099:2 function foo(){console.log(a+1)}
VM1099:4 2

根据实验结果,我们最后得出的排序结果是:

function foo(){};
var a;
a=1;
foo();
var a = 1;
foo();
function foo(){};
提升之后
function foo(){};
var a;
a = 1;
foo();

给你举个更明显的例子
console.log(1, foo, typeof foo);
var foo = "变量";
console.log(2, foo, typeof foo);
function foo(){
    console.log("函数声明");
}
console.log(3, foo, typeof foo);
=》
function foo(){
    console.log("函数声明");
}
var foo;
console.log(1, foo, typeof foo);
foo = "变量";
console.log(2, foo, typeof foo);
console.log(3, foo, typeof foo);
输出为:
1 function foo(){
    console.log("函数声明");
} "function"
2 "变量" "string"
3 "变量" "string"

MDN的描述是正确的,确实是可以等价拆分的,函数声明会被提升到普通变量之前也描述的没毛病。

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

会被转化成

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

等价于

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

ps:var是可以重复声明的,但是从第二次开始的声明从效果来看其实都是无效的

var a=3;
var a;
console.log(a)//3

因为上面等价于
var a
var a
a=3;
console.log(a)//3
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题