ES6 之前,js 只有兩種作用域:
- 全局作用域
- 函數(shù)作用域
是沒有 塊級作用域的
全局作用域變量:
- 不是在函數(shù)內(nèi)部定義的
- 未使用 var 聲明的
函數(shù)作用域變量:
只要在函數(shù)中定義的變量型凳,函數(shù)內(nèi)部都可以訪問到丈冬。即使是后定義的,表現(xiàn)為提升到函數(shù)頂部甘畅,所以函數(shù)任何位置都可以訪問該變量
什么是 變量提升(hoisting):
因?yàn)樽兞可昝魇窃谌我獯a執(zhí)行前處理的(注意埂蕊,只是聲明),在代碼區(qū)中任意地方申明變量和在最開始(最上面)的地方申明是一樣的疏唾。也就是說蓄氧,看起來一個(gè)變量可以在申明之前被使用!這種行為就是所謂的“hoisting”槐脏,也就是變量提升喉童,看起來就像變量的申明被自動移動到了函數(shù)或全局代碼的最頂上。
示例:
輸出: undefined
解析:運(yùn)行之前顿天,先處理所有變量聲明堂氯,全局變量會提升到文件開頭,函數(shù)內(nèi)聲明變量會提升到函數(shù)開頭牌废。所以 var tmp = 'hello' 會將 var tmp 提升至函數(shù)開頭咽白,但是此刻并不會賦值。所以 console 輸出的是 undefined
理解了上面鸟缕,那么下面這個(gè)就好理解了:
所以晶框,建議變量聲明 全局或者函數(shù)最頂上,可讀性好。
繼續(xù):
輸出: 1 2 2.
變量被聲明后三妈,不會再次聲明畜埋,相當(dāng)于:
函數(shù)和變量同時(shí)聲明:
輸出: function foo(){}
如果改成下面形式:
輸出: undefined
輸出: ReferenceError, 因?yàn)檎{(diào)用的時(shí)候莫绣, foo 為 undefined
如果還有一個(gè)同名foo 函數(shù)放到第一個(gè) foo 后面:
function foo () {
console.log('foo2')
}
輸出: ‘foo2'
為什么畴蒲?
函數(shù)提升分為兩種情況:
- 函數(shù)聲明: function foo(){}
- 函數(shù)表達(dá)式: var foo = function(){}
第二種就是聲明一個(gè) foo 變量,然后將一個(gè)匿名函數(shù)賦值給 foo, 和上面變量聲明是一樣的对室。所以輸出 undefined
第一種會將函數(shù)聲明整個(gè)提升到開頭模燥,相當(dāng)于:
并且函數(shù)聲明優(yōu)先于變量聲明,所以掩宜,輸出: function foo(){}
同名的函數(shù)聲明會使用最后一個(gè)
- 首先蔫骂,解釋器掃描Function Declarations,也就是function name{},解釋器將對每個(gè)聲明創(chuàng)建一個(gè)函數(shù)并作為Window的一個(gè)變量
- 解釋器掃描var declarations,作為window的屬性。但是此時(shí)變量并沒有被賦值牺汤,所有的變量此時(shí)都是undefined辽旋。
要徹底理解JS的作用域和Hoisting,只要記住以下三點(diǎn)即可:
1檐迟、所有申明都會被提升到作用域的最頂上
2补胚、同一個(gè)變量申明只進(jìn)行一次,并且因此其他申明都會被忽略
3追迟、函數(shù)聲明的優(yōu)先級優(yōu)于變量申明溶其,且函數(shù)聲明會連帶定義一起被提升
繼續(xù)下面的示例:
輸出: 'foo'
解析: 函數(shù)聲明優(yōu)先于變量聲明,再次聲明都被忽略敦间。
下面輸出什么瓶逃?
輸出結(jié)果:
先彈框:
然后輸出 2
然后又彈框:
最后:
解析:
函數(shù)聲明比表達(dá)式賦值優(yōu)先級高,所以第一個(gè)alert 彈出 聲明的函數(shù)
a() 輸出 2
接下來解析到變量 a 被賦值 var a = function(){}廓块,雖然這個(gè)時(shí)候 a 已經(jīng)被函數(shù)聲明賦值厢绝,但是可以被后續(xù)的賦值覆蓋掉,所以之后 a 的值是第一個(gè)函數(shù)
所以带猴,接下來彈出 1
因?yàn)榇嬖诤瘮?shù)作用域昔汉,所以內(nèi)部定義的變量,外部是訪問不到的浓利,所以報(bào)錯 d 未定義
alert(c) 由于報(bào)錯執(zhí)行不到
解析:
a = null 將 function a() 置成 null 了挤庇,不再是函數(shù)了
let, const 都存在變量提升,但是有點(diǎn)不一樣贷掖。后續(xù)會講到嫡秕。
關(guān)注我,每天更新技術(shù)干貨苹威!