變數宣告系列之ES5(變數提升)
變數宣告恐怕是我們日常開發中最最經常遇到的了,那今天我們就來總結下現在js一共有哪幾種變數宣告的方式以及各個宣告方式的特點。這個變數宣告系列分兩篇文章,一篇寫ES5(var,function)的變數宣告方式及其特點,下一篇寫ES6的變數宣告方式(let,const,class,import)及其特點。
ES5變數宣告方式有var, function。通過這兩種方式宣告的變數特點就是具有“變數提升”的效果,一般想法是一個變數是先聲明後使用,然而如果採用var 或者function宣告的變數和函式(函式表示式不會提升)具有提升的效果。下面詳細說明變數提升究竟是怎麼產生的。
程式碼在引擎中執行之前都會經歷詞法分析
關於變數提升需要注意這幾點:
- 在js中用var ,function宣告的變數都將被提到函式的最頂部。(但是不會初始化)
- 函式宣告的優先順序大於變數宣告的優先順序(function > var )
- 在函式內部變數提升的優先順序會小於函式引數(函式引數 > 函式內部變數提升)
下面輔以例子來具體說明:
console.log(a)
var a = 3;
執行結果如下:
實際上等同於執行下列程式碼:
var a; console.log(a) a = 3;
打印出a的時候,a已近宣告(變數提升的效果)但是並未賦值,自然就是undefined了,如果沒有變數提升的效果此處就會報一個reference erro的錯誤型別了。
再看如下程式碼:
<script>
console.log(f)
f()
var f = 27;
function f(){
console.log('I am function f')
}
console.log(f);
f = 2;
f();
</script>
看看執行結果:
下面我們來分下下為什麼是這個結果呢。?
先var 和function都具有變數提升且根據我們上面的第二條原則function > var 所以第一次列印console.log(f)此時的f是一個函式;
接下來是執行f()自然就會得到f函式內列印的字串'I am function f'再接下來就是給f賦值了此時的f = 27;列印f就會得到數字27,然後又將f的值改為2,再執行f()而此時f已近不是一個函數了,所以控制檯會抱一個typeError的錯誤,表示我們對f的用法錯了(關於各個錯誤型別我們後面會有一篇文章專門說明)。
下面再看看我們所說的第三點:
code:
var age = 0;
function foo(age) {
console.log(age);
var age = 20;
}
foo(27)
console.log(age)
在函式foo中此時傳入的引數age=27,根據我們上述的第三點即函式引數 > 函式內部變數提升。所以在函式內部打印出的age是傳入的引數27,最後一句打印出的age自然就是0了。
有關於函式表示式是否會有變數提升,我看了很多人寫的部落格是說函式表示式並不會有變數提升,我並不贊同這個觀點,我覺得函式表示式也會產生變數提升,事實上只要是用var 與function宣告的變數都會產生變數宣告,但切記用var 宣告的變數不會立馬賦值。看如下程式碼。
code:
console.log(foo)
var foo = function () {
console.log('I am a function foo')
}
實際上在這兒執行的程式碼等同下面的程式碼:
var foo;
console.log(foo)
foo = function () {
console.log('I am a function foo')
}
所以函式表示式也同樣有變數提升的效果。