1、瀏覽器的解析過程
1、預解析
在預解析之初,即在js的“ = ”
號發(fā)揮作用之前,先會做三件事:
??最先尋找?guī)в?strong>var
的變量,找到帶有var的變量然后并賦予為undefined(這就是變量提升);
??其次找到函數(shù),此時的函數(shù)是找到整個函數(shù)塊,并不會對其進行解析。
2、逐行解讀代碼
從上到下解讀表達式:(能改變數(shù)值的)=+-%*/++—!參數(shù)number()等,表達式可以修改預解析的值。
那就看例子,例子最能說明一切:
Eg1:
console.log(a)
var a = 1;
console.log(a)
function a() {
console.log(a)
}
console.log(a)
var a= 3;
console.log(a)
function a() {
console.log(a)
}
console.log(a)
console.log(typeof a)
a()
解析:
第一個結(jié)果:function a() { console.log(a) }
因為在預解析中若遇到重名只留下一個,當var 和 函數(shù)重名時,只留下函數(shù)。var解析a為undefined,將被函數(shù)覆蓋。因為先尋找var定義的變量,找到后進行賦值undefined,隨后找到函數(shù)塊,會將同名變量進行覆蓋,所以第一個console.log為最后一個遇到的函數(shù)。
第二個結(jié)果:1
從上往下進行賦值,原本還是函數(shù)的a已經(jīng)被重新賦值。
第三個結(jié)果:1
函數(shù)沒有被調(diào)用,不會產(chǎn)生影響,所以結(jié)果還是1。
第四個結(jié)果:3
遇到同名變量,被重新賦值。
第五個結(jié)果:3
函數(shù)沒有被調(diào)用,不會產(chǎn)生影響,所以結(jié)果還是3。
第六個結(jié)果:number
在第一個變量a的時候,就已經(jīng)把預解析的函數(shù)給cover了,所以,此時的a已經(jīng)不是函數(shù),而是數(shù)字。
第七個結(jié)果:TypeError報錯
既然a都已經(jīng)不是函數(shù)了,自然無法調(diào)用,就會進行報錯。
Eg2:
var a= 1;
function fn() {
console.log(a)
var a = 2
}
fn()
console.log(a)
解析:
第一個結(jié)果:undefined
函數(shù)在逐行解讀代碼時,遇到函數(shù)調(diào)用也會按照解讀順序,進行預解析,逐行解讀代碼。
第二個結(jié)果:1
因為函數(shù)存在作用域,局部變量只能在作用域內(nèi)訪問,能訪問外部變量,卻不能修改,離開了作用域則會被垃圾回收機制回收,所以,結(jié)果為1。
Eg3:
var a = 1;
function fn() {
console.log(a)
a= 2
}
fn()
console.log(a)
解析:
第一個結(jié)果:1
若當函數(shù)中沒有var 解讀不到時,函數(shù)會回到父級中尋找var,將父級中的var a帶入函數(shù)中。這就是作用域鏈。
第二個結(jié)果:2
a = 2 為全局變量,可以改變外部變量的值,所以,在外部訪問時,打印結(jié)果為2。
Eg4:
var a = 1;
function a(a) {
console.log(a)
a= 2
}
fn()
console.log(a)
解析:
第一個結(jié)果:1
在函數(shù)內(nèi)的解析中,先進行預解析,預解析找到參數(shù)a,由于參數(shù)a相當于var a,在上面代碼中并未進行賦值,所以打印出來是undefined。
第二個結(jié)果:2
隨后當a被賦值2時,先找找本函數(shù)中的var a,若是找到,則修改本局部函數(shù)中的a,若未找到,則會向上查找,找到作用域外部的a,將全局函數(shù)中的a修改。
Eg5:
var a = 1;
function a(a) {
console.log(a)
a= 2
}
fn(a)
console.log(a)
解析:
第一個結(jié)果:1
函數(shù)調(diào)用中,賦予的參數(shù)a,調(diào)用的是全局函數(shù)中的值1,相當于將1代入函數(shù)中。
第二個結(jié)果:1
函數(shù)中的a = 2能夠在函數(shù)中找到var a,所以此時修改的是當前函數(shù)內(nèi)的a,而不會向上查找修改全局變量a,所以函數(shù)作用域外部的變量依然還是1。
如果這些代碼,全都能搞定并說出原因,我想,關(guān)于Javascript變量提升的問題應該不大了吧~