詞法作用域
一、作用域
定義:就是作用范圍
作用域說明的是一個(gè)變量可以在什么地方被使用,什么地方不能被使用。
1.塊級(jí)作用域
JavaScript中沒有塊級(jí)作用域概念
所以只要聲明過的變量,在訪問的時(shí)候就不會(huì)報(bào)錯(cuò)。
在JavaScript中作用域規(guī)則:
- 函數(shù)允許訪問函數(shù)外的數(shù)據(jù)
- 整個(gè)代碼結(jié)構(gòu)中只有函數(shù)可以限定作用域
- 作用域規(guī)則首先使用特生規(guī)則分析
- 如果當(dāng)前作用規(guī)則中沒有名字了,就不考慮外面的名字。
二、變量提升
fun();
function(){
alert(123);
}
//實(shí)際語法中沒有報(bào)錯(cuò),因?yàn)镴avaScript并非在運(yùn)行簡單的逐句解析執(zhí)行。
JavaScript預(yù)解析
JavaScript引擎在對JavaScript進(jìn)行解釋執(zhí)行之前,會(huì)對JavaScript代碼進(jìn)行預(yù)解析階段,會(huì)以關(guān)鍵字var
和function
開頭的語句塊提前進(jìn)行處理。
當(dāng)變量和函數(shù)聲明的處在作用域比較靠后的位置的時(shí)候,變量和函數(shù)的聲明會(huì)被提升到作用域的開頭。
聲明、定義、初始化
的區(qū)別:
- 聲明:告訴解析器有這個(gè)變量存在,這個(gè)行為是不分配內(nèi)存空間的,在JavaScript中,聲明一個(gè)變量的操作為
var a;
- 定義:在變量分配內(nèi)存空間,在C語言中,一般生命就包含了定義,比如:int a;但在JavaScript中,var a 這種形式只是聲明。
- 初始化:在定義變量之后,系統(tǒng)為變量分配的空間內(nèi)存儲(chǔ)的值是不確定的,所以需要對這個(gè)空間進(jìn)行初始化,以確保程序的安全性和確定性。
- 賦值:賦值就是變量在分配空間之后的某個(gè)時(shí)間里,對變量的值進(jìn)行刷新操作(修改存儲(chǔ)空間內(nèi)的數(shù)據(jù))
所以,本文提到的提升,是聲明的提升。
預(yù)解析是分作用域的
聲明變量并不是將所有的聲明都提升到window對象下面,提升原則是提升到變量運(yùn)行的環(huán)境(作用域)中。
函數(shù)表達(dá)式并不會(huì)被提升
func();
var func = function(){
alert("我被提升了");
}
//這里會(huì)直接寶座找不到函數(shù),原因是var fun = function(){},這種函數(shù)表達(dá)式,并不會(huì)被提升,只是簡單了對變量進(jìn)行了處理。
三、作用域鏈
什么是作用域鏈?只有函數(shù)可以制造作用域結(jié)構(gòu),只要是代碼,就至少有一個(gè)作用域,即全局作用域。
凡是代碼中有函數(shù),那么這個(gè)函數(shù)就構(gòu)成另一個(gè)作用域。如果函數(shù)中還有函數(shù),那么在這個(gè)作用域就又可以誕生一個(gè)作用域。將這樣的作用域列出來,就會(huì)出現(xiàn)一個(gè)結(jié)構(gòu),函數(shù)內(nèi)指向函數(shù)外的鏈?zhǔn)浇Y(jié)構(gòu),稱為作用域鏈。