0x00颠悬、引言
為了對(duì)JavaScript的作用域和作用域鏈有一個(gè)更好的理解,我們就需要了解JS這門語言的一個(gè)機(jī)制定血,即聲明前置赔癌。
0x01、從變量的聲明前置說起
我比較喜歡從一些小的demo來說起和加深自己對(duì)JavaScript這門語言機(jī)制的理解澜沟,那么聲明前置這個(gè)也不另外
- demo1
console.log(a) // undefined var a = 1 console.log(a) //1
第二個(gè)console.log(a) 打印出1我們好理解届榄,那么上面為什么第一個(gè)console會(huì)打印出undefined?
這里就不得不提一直說的聲明前置倔喂,其實(shí)var a = 1可以拆解為var a
和a = 1
這樣兩個(gè)部分了铝条,var a
是對(duì)變量a的聲明,a = 1是對(duì)變量a的賦值席噩,所謂聲明前置就JS引擎在解析這段代碼的時(shí)候班缰,會(huì)將var a
聲明放置在最前面,即可以改寫為以下代碼
-
demo1改寫
var a //變量a聲明前置了
console.log(a) // undefined
a = 1
console.log(a) //1
下面我們?cè)賮砜匆粋€(gè)例子
- demo2
console.log(a) // undefined
if (false){
var a
}
這里我們將var a放置在if 語句中悼枢,還會(huì)聲明被前置么埠忘,結(jié)果是當(dāng)然,因?yàn)樵赱深入之作用域](http://www.reibang.com/p/636c5eb548e2)中我們以及知道在JS這門語言中只有全局作用域和函數(shù)作用域馒索,無塊級(jí)作用域(ES6有新增)莹妒,**因而var a 即使在if/for里面,也會(huì)被前置的**
##### 0x02绰上、關(guān)于函數(shù)的聲明前置
我們知道函數(shù)有多種的調(diào)用方式旨怠,但我們這里主要討論函數(shù)的聲明前置,所以當(dāng)用到函數(shù)的調(diào)用就以最簡單的一種函數(shù)調(diào)用模式為例
- demo3
fn(2,3); //5
function fn(a,b) {
return a+b;
var c = 1
}
在這個(gè)簡單的函數(shù)調(diào)用中蜈块,在JS中將定義的函數(shù)進(jìn)行一個(gè)聲明前置鉴腻,確保它在被調(diào)用前以及被定義了,下面我們可以改寫為以下形式
- demo3改寫
function fn(a,b) { //全局作用域下定義的函數(shù)fn聲明前置
var c //函數(shù)作用域內(nèi)聲明變量c前置
return a+b;
c = 1
}
fn(2,3); //5
#### 0x03百揭、下面舉出幾個(gè)復(fù)雜一點(diǎn)的例子
> 1.若不報(bào)錯(cuò)爽哎,下面代碼輸出什么?
var y = 10;
if (!(x in window)) {
var x = 10;
} else {
++y;
}
alert(x); //undefined,var a 即使在if/for里面器一,也會(huì)被前置的,
//但a=10的賦值還會(huì)停留在if(){...}中
alert(y); //11
> 2.重復(fù)聲明兩個(gè)函數(shù)會(huì)怎樣课锌?
var m= 1, j = k = 0;
function add(n) {
return n = n+1;
}
y = add(m); //4,由聲明前置我們可以知道后一個(gè)函數(shù)將在y調(diào)用前聲明并覆蓋掉前一個(gè)函數(shù)的聲明(同名)
function add(n) {
return n = n + 3;
}
z = add(m); //4,z和y的指針其實(shí)指向的其實(shí)是同一個(gè)函數(shù)
> 3.對(duì)下面進(jìn)行聲明前置的改寫
a = 2
b()
var a
function c(){
console.log(a)
}
function b(){
a = 1
c()
var a
}
/------改寫------/
var a //全局作用域內(nèi)的變量a提升
function c(){ //聲明函數(shù)的變量提升
console.log(a) //重點(diǎn) 祈秕,此時(shí)的a指的是全局變量的a
}
function b(){ //聲明函數(shù)的變量提升
var a //函數(shù)作用域內(nèi)的變量a提升
a = 1
c() //c()函數(shù)被調(diào)用
}
a = 2
b() //2