js引擎在執行整個js**的過程中,分為倆步。第一步是讀取和解析js**,第二部是執行。
在引擎解析js**的時候,當解析器遇見變數宣告(var 變數名)和函式宣告
(function 函式名)的時候,會將這些宣告提到各自作用域的最前面。
在es6之前,js是沒有塊級作用域的。只有2種作用域:
注:在其他語言中,被稱為**塊,所形成的作用域被稱作塊級作用域,如:
if
(...
)for
(var i =
0;i<
5;i++
) console.
log(a)
; console.
log(b)
; console.
log(i)
;
如果以上倆例子有塊級作用域的話,a,b,i是不能被訪問到的,但是在js中是可以的(es6之前),所以沒有塊級作用域。
首先我們宣告變數是通過var關鍵字,如果不用var直接賦值的話會被解析器當作是全域性變數。但是切記,變數的提公升只限於用var宣告的變數,沒通過
var宣告的變數將不會被提公升。看下邊的例子:
var a =1;
console.
log(a)
;// 1
// 輸出的結果為1,沒問題,因為**在執行的時候是按順序執行的。
// 解析的時候,經過變數提公升後的結果如下:
var a;
a =1;
console.
log(a)
;// 1
console.
log(a)
;// undefined
var a =1;
// 這次的結果輸出為undefined,我們都知道,當乙個變數宣告了卻未賦值的時候就會出現undefined,
// 但是乙個變數沒有宣告的話,就會輸出 a is not defined,先看本例經變數提公升後的結果:
var a ;
console.
log(a)
;// undefined
a =1;
// 所以由此可見,變數的提公升只會提公升變數的宣告,而不會提公升變數的賦值。
console.
log(a)
;// a is not defined
a =1;
// 當我們把var去掉的時候,結果變成了 a is not defined,很明顯,沒有var宣告的變數,沒有被提公升至作用域的最前邊,也就是變數提公升只是對用var宣告的變數而言的。
函式的內部也是如此
(
function()
)()提公升結果如下:
(function()
)()
只有用var宣告的變數才存在變數提公升這一說法變數提公升只提公升變數的宣告,不會提公升賦值這一部分;
函式的宣告有倆種方式,一種為:
functionfn(
)//另一種為:
varfn
=function()
// 首先的我們得知道函式屬於引用型別,函式名實際上相當於乙個指標,儲存的是函式體所在的位址,所以函式也可以通過函式表示式var fn來宣告,但是同為函式,他們的提公升結果卻是不同的。
functionfn(
)fn()
;// hello
// 結果輸出為hello,這個不難理解,**的順序執行。函式提公升後的結果還是這樣。
fn()
;// hello
functionfn(
)// 執行結果還是hello,因為函式在解析**的時候,同樣,函式的宣告被提到了作用域的最前邊,如下:
functionfn(
)fn()
;// hello
// 需要注意的是整個function fn()均為函式的定義(宣告)。
varfn=
function()
fn();
//hello
// 用var宣告的函式同變數一樣,先把定義提公升至最前邊,如下:
var fn;fn=
function()
fn();
//hello
fn()
;//fn is not a function
varfn
=function()
// 但是將用var宣告的函式放在後邊就不行了,因為這樣宣告的函式,提公升後是下邊這樣的:
var fn;
fn()
;//fn is not a functionfn=
function()
// 同變數提公升一樣,提公升的只是定義,並沒有賦值。
console.
log(a)
;functiona(
)console.
log(a)
;var a =3;
//變數
console.
log(a)
;執行結果如下:
functiona(
)functiona(
)3
console.
log(a)
;var a =3;
console.
log(a)
;functiona(
) console.
log(a)
;
由此可見
倆次舉例中,函式和變數是同名的,在**未執行到變數賦值語句的時候,console列印出來的均為函式,變數賦值以後,列印的才是剛剛賦的值,所以由綜合例子可以得出:當變數和函式同名時,函式的優先順序高!
由以上的例子不難看出變數提公升和函式提公升的特點,可以總結如下:所有的宣告都會提公升到各自作用域的最頂上去。
只有用var宣告的變數才存在變數提公升這一說法
變數提公升只提公升變數的宣告,不會提公升賦值這一部分;
同乙個變數只會宣告一次,其他的會被忽略掉。
函式宣告的優先順序高於變數宣告的優先順序
所有變數的宣告,在函式內部第一行**開始執行的時候就已經完成。
JS 變數提公升與函式提公升
在 es6 出來之前,沒有塊級作用域,只有全域性作用域 和 函式作用域。變數提公升指的是 將變數宣告提公升到它所在作用域的最開始部分。例子 console.log foo undefined var foo 變數提公升 console.log foo 變數提公升 相當於 var foo consol...
js中的變數提公升和函式提公升
一,變數提公升 顧名思義,變數提公升就是函式在執行時,會把在下面的變數提公升到函式的top位置,來看栗子 var scope hello function t t 此時輸出的結果是 第乙個輸出undefined 根據作用域鏈,函式內部訪問乙個變數時,會首先在作用域鏈的前端也就是函式內部尋找變數,找到...
js中的變數提公升和函式提公升
從上週開始,我所在的學習小組正式開始了angular的學習,angular是全面支援es6的,所以語法上和以前的angular有了很大的不同,比如變數宣告時就拋棄了var,而選擇了let和const 記得剛開始學習js的時候,使用webstrom時用var,webstrom會在下面畫一條小綠線,表示...