关于变量和函数的提升问题
今天碰见了函数的提升问题:阅读以下代码:
var foo = function(){ console.log("仙女"); } function foo(){ console.log("魔鬼"); } foo();//打印仙女
解析顺序为:
function foo() { console.log("魔鬼") } var foo; foo = function(){ console.log("仙女"); } foo()
到这我就有问题了:
一般来说变量和函数的提升,整体来说,变量声明是在函数之后,那为啥上面的解析顺序就var变量在后,function在前呢?
这个就涉及到函数声明在前还是变量声明在前之争。
有些人认为:函数声明在前,有些人认为变量声明在前。
我个人更偏向变量声明在前。
function f() { console.log(num); //undefined } f(); var num;
这里函数里面能访问到num,证明变量的声明会在函数之前。
--------------以上为自己未搞清原理之时,单一的揣测,读者可认真阅读以下内容--------------
经查询JavaScript(第6版),书中没有明确说明函数声明在前还是变量在前,只是说明了:
var scope="global scope";//全局变量 function checkscope() { var scope="local scope";//局部变量 function nested() { var scope="nested scope";//嵌套变量 return scope; } return nested(); } console.log(checkscope());// 输出 nested scope
书中似乎对于变量声明在前还是函数声明在前没有很纠结,只是“大方地”说了在函数体内,局部变量的优先级高于同名的全局变量。如果函数在函数内声明的一个局部变量或者函数参数中带有的变量和全局变量重名,那么全局变量就被局部变量所遮盖。
由于JavaScript中没有块级作用域,JavaScript取而代之地使用了函数作用域(function scope):变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。
function test(o){ var i=0; if(typeof o== "object") { var j=0; for(var k=0;k<10;k++) { console.log(k); } console.log(k); } console.log(j); } var arr={ name:"spot", addredd:"jiangsu" } test(arr);
JS的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的,有意思的是,这意味着变量在声明之前甚至已经可用。JavaScript的特性被非正式地称为声明提前(hoisting),即JavaScript函数里声明的所有变量(但不涉及赋值)都被“提前”至函数体的顶部。
如一个问题:
var x=1; function rain() { alert(x);//弹出 ‘undefined’,而不是1,也不是0,why? var x="10"; alert(x); } rain(); //如果该作用域中有,就不会去上级作用域中拿
你可能会误以为函数中第一行会弹出“1”,因为代码还没执行到var 语句声明局部变量的地方。其实不然,由于函数作用域的特性,局部变量在整个函数体始终是有定义的,也就是说,在局部体内局部变量遮盖了同名全局变量。尽管如此。只有在程序执行到var语句的时候,局部变量才会被真正赋值。因此,上述过程等价于:将函数内的变量声明“提前”至函数体内部,同时变量初始化留在原来的位置。
上述代码相当于:
var x=1;
function rain() { var x; alert(x); var x="10"; alert(x); } rain();
在具有块级作用域的编程语言中,在狭小的作用域里让变量声明和使用变量的代码尽可能靠近彼此,通常来讲,这是一个非常不错的编程习惯。由于JavaScript没有块级作用域,因此一些程序特意将变量声明放在函数体顶部,而不是将声明靠近放在使用变量之处,这种做法使得他们的源代码非常清晰地反映了真实的变量作用域。
在查看了相关博客后,查看底层原理,其实函数声明是在变量声明之前。
博客在此:https://segmentfault.com/a/1190000014899566
所以,结论为:函数声明在前,变量声明在后。
--------------搞清原理后,再返回来看看上述内容--------------
var foo = function(){ console.log("仙女"); } function foo(){ console.log("魔鬼"); } foo();//打印仙女
解析顺序为:
function foo() { console.log("魔鬼") } var foo; foo = function(){ console.log("仙女"); } foo()
对于第二个问题:
function f() { console.log(num); //undefined } f(); var num;
实则是这样的
function f() { var num; console.log(num);//undefined } f();
var num;