變量和函數聲明提高發生在JavaScript預編譯階段。函數
所謂的聲明提高,就是說變量或者函數在聲明的時候會被提早到當前做用域的頂部,已經處於可訪問狀態。code
var scope = 'global'; function f(){ console.log(scope);//undefined var scope = 'local'; console.log(scope);//"local" }
因爲函數體內存在變量聲明提高,因此上面代碼實際運行以下:ip
var scope = 'global'; function f(){ var scope; //變量聲明提高到函數頂部 console.log(scope); scope = 'local'; //變量初始化依然保留在原來的位置 console.log(scope); } f();
這裏須要注意,函數體內存在和全局做用域同名的變量scope,做用域鏈查找到當前函數體內發現局部變量scope,不會再去查找全局做用域當中變全局量scope了,簡而言之函數體內的局部變量會覆蓋全局同名變量內存
若是隱式聲明一個變量,那麼該變量是存在於全局做用域當中的。作用域
var scope = 'global'; function f(){ scope = 'local'; } f(); console.log(scope);//"local"
上面代碼,函數f內至關於對全局變量scope進行賦值get
建立函數有兩種方式,函數聲明和函數表達式,只有函數聲明存在提高。編譯器
//函數聲明 f('superman'); function f(name){ console.log(name); } //函數表達式,報錯 f('superman'); var f= function(name){ console.log(name); }
看下面代碼:io
var getName = function(){ console.log(2); } function getName (){ console.log(1); } getName();//2
上面代碼實際運行以下:console
var getName; //變量聲明提高 function getName(){ //函數聲明提高到頂部 console.log(1); } getName = function(){ //變量賦值依然保留在原來的位置 console.log(2); } getName(); // 最終輸出:2
函數聲明提高的優先級是高於變量聲明的,這裏的優先級指的是:同名的變量和函數中,函數先提高,再遇到同名的變量或函數,提高都將被編譯器忽略。編譯
//同時聲明變量a和函數a var a; function a() {} alert(typeof a); //顯示的是"function",初步證實function的優先級高於var。 //先聲明函數後聲明變量,證實上邊的例子不是function覆蓋了變量 function a() {} var a; alert(typeof a); //顯示的還是"function",而不是"undefined",即function的優先級高於var。
注意,上面只是說聲明的狀況,若是變量同時賦值,有不同了
//聲明瞭變量的同時賦值 function a() {} var a = 1; alert(typeof a); //number,此時不是function了。 //說明:"var a=1"至關於"var a;a=1",即先聲明,後賦值,"a=1"至關於把a從新賦值了,天然就是number!
getName() var getName = function () { alert('closule') } function getName() { alert('function') } getName()
上邊的代碼至關於:
function getName() { //函數向上提高 alert('function') } getName() var getName = function () { alert('closule') } getName()
<script> getName() var getName = function () { alert('closule') } <script> <script> function getName() { alert('function') } <script>
代碼執行報錯:TypeError: getName is not a function,由於第一個<script>塊中getName()函數未定義,匿名函數又不會向上提高