JS變數提公升

2021-09-25 05:10:13 字數 4073 閱讀 5652

在當前作用域中,js**自上而下執行之前,瀏覽器首先會把所有的帶var/function關鍵字的進行提前宣告/定義。

注意宣告和定義的區別:

宣告(declare):var num;在當前作用域中吼一嗓子我有num這個名字了。

定義(define):num = 12;把宣告的名字賦值。

console.

log(a)

;//=>undefined

console.

log(fn)

;//=>輸出fn的函式體fn(

);//=>undefined, 1

var a =12;

functionfn(

)console.

log(a)

;//=>12

帶var關鍵字的只是提前宣告一下,帶function關鍵字的在變數提公升階段把宣告和定義都完成了。

注:var fn = function( )和function fn( )不一樣。

fn2()

;//=>fn2

function

fn2(

)// 因為var關鍵字宣告的函式,只宣告,不定義,所以不能再函式體之前執行。

console.

log(fn1)

;//=>undefined

fn1();

//=>typeerror: fn1 is not a function

varfn1

=function()

;

在全域性作用域中的區別:

【帶var】:var a;在全域性作用域中宣告了乙個變數,同時也給全域性物件window設定了乙個屬性叫做a

【不帶var】:a = 12;不帶var的情況在全域性作用域和私有作用域中都一樣。不帶var,則僅僅是給全域性物件設定了乙個新的屬性名。

注:在js中呼叫window的屬性和方法時,window可以省略。

舉個栗子:

//帶var

//變數提公升階段:在全域性作用域中var a;同時window.a = undefined

console.

log(a)

;//=>undefined

var a =12;

//**從上到下執行:a = 12; 全域性作用域中的a=12,同時window.a = 12

console.

log(a)

;//=>12

console.

log(window.a)

;//=>12

// 不帶var

// 沒有var就沒有變數提公升

console.

log(a)

;//referenceerror: a is not defined

//沒有變數提公升,所以這裡查詢的是全域性作用域中的變數a

a =12

;//這裡的賦值只是給全域性物件window中的a賦值,相當於window.a = 12;

console.

log(a)

;//=>12 這裡輸出的是window.a

console.

log(window.a)

;//=>12

在私有作用域中:
// 帶var

functionfn(

)fn()

;console.

log(a)

;//referenceerror: a is not defined

//閉包機制:私有作用域保護裡面的私有變數不受外界干擾

// 不帶var

functionfn(

)fn()

;console.

log(a)

;//=>12

console.

log(window.a)

;//=>12

等號=:賦值,等號左邊是變數,右邊是值(不管寫什麼都是值)。

item.classname = i%

2===0?

'c1'

:'c2'

;

匿名函式:函式表示式(把函式當做乙個值賦值給變數或者其他內容)。
fn()

;//typeerror: fn is not a function

varfn

=function()

fn();

專案中,一般用函式表示式建立函式,因為這種方法只對函式左邊進行變數提公升,當前函式只有宣告沒有定義,因為只在賦值的**之後執行,這樣讓**邏輯更加嚴謹。
varfn=

function

sum();

fn();

sum();

//referenceerror: sum is not defined

console.

log(num)

;//=>undefined

console.

log(fn)

;//=>undefinedif(

1===1)

}console.

log(num)

;//=>12

console.

log(fn)

;//=>[function: fn]

console.

log(num)

;//=>undefined

console.

log(fn)

;//=>undefinedif(

1!==1)

}console.

log(num)

;//=>undefined

console.

log(fn)

;//=>undefined

注意三點:

1)不管條件是否成立,判斷體**現的var/function都會進行變數提公升,但在最新版本的瀏覽器中,function宣告的變數只能提前宣告不能定義了(前提:函式定義在判斷體中)。

2)當**執行到條件判斷的地方:(新版本瀏覽器)

【條件不成立】:進入不到判斷體中,此時之前宣告的變數和函式依然是undefined。

【條件成立】:進入到判斷體中的第一件事,就是把之前變數提公升時沒有定義的函式首先定義了(進入到判斷體中函式就定義了:迎合es6中的塊級作用域)。

3)老版本的李蘭器不是這樣處理的。老版本中,不管條件是否成立,都要進行變數提公升(和新版本不一樣,新版本function只宣告,老版本function依然是宣告+定義)。

練習題:

// 變數提公升:沒有(沒有var就沒有變數提公升)f=

function()

;g=function()

;// **執行到這給window新增了兩個屬性:f和g。

~function()

functiong(

)}}(

);// 老版本瀏覽器下的結果

console.

log(f(

));//=>false

console.

log(g(

));//=>false

在變數提公升階段,若名字重複了,不會重新進行宣告,但會重新進行定義(後面賦的值會把前面賦的值給替換掉)。

舉個栗子:

// 變數提公升:fn = aaafff111 (=aaafff222) (=aaafff333) (=aaafff444)fn(

);//=>4

functionfn(

)fn()

;//=>4

functionfn(

)fn()

;//=>4

functionfn(

)fn()

;//=>4

js變數提公升

在了解變數提公升之前,應該先了解一下js到底是一種什麼型別的語言,他的執行機制又是怎樣的.console.log global undefined var global global console.log global global function fn fn 可以看出來 變數提公升只是將變數提...

js變數提公升

var a 100 functionf console.log a f undefined 200var a 100 functionf f console.log a 100如果你習慣了強型別語言的程式設計方式,那麼看到上述輸出結果你肯定會大吃一驚。我們來看一下c 的乙個例子 include us...

js變數提公升

function say say 在js中,瀏覽器在執行 前會有一次預編譯,這個過程會把函式宣告和變數宣告提公升到作用域的頂端,並賦值undefind,這個過程就叫提公升 並且在js中,函式是一等公民,優先順序是最高的,稍後會解釋 這就不難理解剛才那道題了,上面的 編譯後如下 function sa...