作用域 提前宣告和閉包

2021-08-28 18:40:39 字數 2838 閱讀 6639

在es6之前,只有全域性作用域和函式作用域,es6的let和const讓塊級作用域成為可能;

全域性作用域:

全域性作用域是最大的最根本的作用域,在它上面宣告的變數是全域性變數,可以在任何地方被訪問的,只要沒有被變數覆蓋;

函式作用域:

存在於函式呼叫的時候,在函式中所有宣告的變數,只有在函式被呼叫的時候才會出現其函式作用域,出現函式作用域的前提是函式內的變數通過var宣告:

function

foo(

)foo()

console.

log(x)

;//報錯

這段**說明,函式中宣告的x是區域性變數,在外部無法訪問到;

function

foo(

)foo()

console.

log(x)

;//2

而把函式中變數宣告前的var去掉之後,在函式體的外部也就可以訪問到了,這說明此時的x已經成為了全域性變數,這和作用域鏈和js的變數賦值過程有關:

當出現類似x=2這種**的時候,js缺省會執行賦值操作(這本身就是乙個賦值語句),當**執行到x=2這個賦值操作的時候,js會先去當前作用域中查詢x這個變數是否存在,如果當前作用域中不存在x,則會順著作用域鏈向上(向著父輩)查詢,在哪個作用域中找到了,這個x就會賦值為2,如果一直找到全域性作用域都還沒找到,則說明根本不存在x這個變數,js就會幫你在全域性作用域中宣告乙個x變數,然後進行賦值操作;(所以有些人認為沒有用var直接進行x=2直接宣告的就是全域性變數,其實是有問題的),如:

function

foo())

()console.

log(x)

;//4

}foo()

console.

log(x)

;//報錯

這裡在最裡面的匿名函式中進行了x=4的賦值操作,但是該匿名函式作用域中並沒有x變數,於是會沿著作用域鏈向上查詢,在foo()的作用域內找到了x變數,則進行了賦值操作,不用再繼續查詢,x沒有變成全域性變數,所以外部的x是找不到的;

其他:對於if,while,for等操作,在其他語言中,這些都是塊級作用域,但是對於js來說,它沒有塊級作用域(es6以前,當然也可以通過閉包的達到類似的效果),如果在這些**塊中用var宣告變數,宣告的變數會直接上浮到if外層的作用域,導致變數被外部訪問汙染;

同級別的函式和if中的var x=2;前者只能在函式作用域內被訪問,而後者可以在if外面被訪問的,甚至可以理解為,if塊沒有自己的作用域;

在es6中,js才有了塊級作用域,通過let申明,即使是在if**塊中的宣告,也不會被外部汙染;

函式宣告提前:

foo()

;//成功呼叫並列印出3

function

foo(

)

函式宣告提前可以讓函式提前被呼叫;

變數宣告提前:

變數宣告的提公升只針對var,通過let和const宣告的變數都不會有提前的現象;

foo()

;function

foo(

)

此外,通過匿名函式賦值來宣告的函式,只會提前宣告變數名,無法提前呼叫:

fo()

;//報錯

varfo

=function()

var s =fo;

//不會報錯

console.

log(fo)

;//undefined

varfo

=function()

注釋:

1.提前宣告只能提前到當前作用域的最前面

2.提前宣告只會提前變數名,不會提前賦值

閉包就是能夠讀取其他函式內部變數的函式。

閉包的用處,乙個是可以讀取函式內部的變數,另乙個就是讓這些變數的值始終保持在記憶體中。

能讀取到函式內部的區域性變數的只有函式內部的東西,因此在利用閉包的時候,比如會在函式內宣告乙個函式,又為了讓這個函式之外的函式訪問到,所以會通過return返回出去:

functionf1(

)functionf2(

)return f2;}f1

()()

;//1

此時,在f1外已經獲取到了n的值,

functionf1(

)functionf2(

)return f2;}f1

()()

;//1

add()f1

()()

;//1

add(

);

執行發現兩次執行n的值未發生改變,因為在執行一次之後函式執行所佔的記憶體被**了,所以想要實現個函式的原本功能,必須要讓n的值保持在記憶體中,n才能實現累加:

functionf1(

)functionf2(

)return f2;

}var x =f1(

);x(

);add(

)//1x(

);add();

//2

將f1賦值給x,f1()呼叫返回回來的f2會儲存在x中,也就是會儲存在記憶體中,而f2()是依賴於f1()而存在的,所以f1()也會存在於記憶體中,n也會存在於記憶體中,於是就實現了累加的效果;

不過這樣會不停的占用記憶體,導致記憶體洩漏,所以閉包能不用還是不要用了;

作用域和閉包

給執行上下文環境下乙個通俗的定義 在執行 之前,把將要用到的所有的變數都事先拿出來,有的直接賦值了,有的先用undefined占個空。全域性 的上下文環境資料內容為 1 普通變數 包括函式表示式,如 var a 10 宣告 預設賦值為undefined 2 函式宣告 如 function fn 賦值...

作用域和閉包

題目 知識點 1 執行上下文 2 this 3 作用域 4 作用域鏈 5 閉包 一 執行上下文 ps 函式宣告和函式表示式的區別 執行上下文 console.log a undefined var a 10 fn 張三 22 張三 22 function fn name 在script標籤內的全域性...

作用域和閉包

現有宣告後有賦值 宣告在編譯時會提公升位置,提公升時函式會優先變數,如果是同名函式順序排在後面的會覆蓋前面的函式 函式表示式 立即執行的函式表示式 var a 2 function iife global window 塊作用域和閉包 閉包 function foo return bar var b...