在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...