JS函式提公升和變數提公升

2021-09-25 22:19:30 字數 3547 閱讀 3446

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會在下面畫一條小綠線,表示...