今天小編給大家分享的是js中的變量提升機制介紹,相信很多人都不太了解,為了讓大家更加了解js中的變量提升機制,所以給大家總結了以下內容,一起往下看吧。一定會有所收獲的哦。
變量提升
JavaScript的變量提升有兩種,用var聲明的變量以及用function聲明的變量。
用var聲明的變量
我們先來看下面這段代碼,a的值是多少
代碼1
console.log(a); var a;
按照以往編程語言的思路來看,代碼自上而下運行,按這種思路,會報錯,因為執行到第2行時,變量a還沒有定義,所以會報錯a is not defined
然而事實上答案是undefined
好,抱著疑惑,我們看下面的代碼
var a; console.log(a);
我們發現,這兩段代碼是一樣的,那么又有一個新的問題,是不是有沒有var a都無所謂,它的答案始終是undefined,才造成了以為變量會提升的錯覺,于是我寫了代碼3
代碼3
console.log(a);
好,它終于報錯了,所以這證明了javaScript代碼并不是自上而下執行的,至少從表面看上面是這樣的。
于是我們再看代碼4
代碼4
console.log(a); var a = 2;
因為變量提升嘛,所以答案是2,然而事實上,它依然是undefined,why?
這時候我們有請編譯器這位負責語法分析及代碼生成等臟活累活的大佬。
編譯器在看到var a = 2;,它會將其看做兩個聲明,var a;和a = 2,第一個聲明在編譯階段進行,第二個聲明會被原地等待執行階段。
也就是說上面代碼,會變成下面的這段代碼
var a; console.log(a); a = 2;
所以最終會是undefined
好,我在啰嗦一下,看這段代碼5
代碼5
a = 2; var a; console.log(a);
我想大家應該已經知道這段代碼執行時的真正順序及其答案了,沒錯,答案是2,但我想說的是把第2行給注釋掉,答案依然是2,但這個和變量提升沒啥關系了,是嚴格模式與非嚴格模式的鍋,在非嚴格模式下允許開發者可以不使用聲明變量的關鍵字,但在嚴格模式下是不可以的,它會報錯的。
用function聲明的變量
與var一樣,function聲明的變量依然會提升。
log(5);
function log(mes){
console.log(mes)
}按照之前的變量提升的理解,這段代碼的真正順序是這樣的,
function log(mes){
console.log(mes)
}
log(5);很好,很正確,那么再看下一段代碼
log(5);
var log = function(mes){
console.log(mes)
}它報錯了,log is not a function,從這里我們可以看出,這種函數表達式是不會被提升的,只有函數聲明才會被提升,試著在最前面新增一行代碼console.log(log),會先輸出undefined。
所以這里的真正順序是
var log;
log(); //這時候只是聲明了log這個變量,并不是函數,卻用函數的方法調用它,所以會報錯,說這不是一個函數。
log = function(mes){
console.log(mes)
}在function里用var聲明變量
我們雖然知道,var聲明的變量會提升,但并不知道會提升到哪個程度。
在此之前來看一段代碼
var a = 4;
function foo(){
var a = 5;
console.log(a);
}
foo();
console.log(a)答案是5,4,先輸出5,再輸出4。
用var聲明的變量是有函數作用域的,所以foo里的a和foo外面的a沒有任何關系,這種情況正是我想要的。
再改下代碼
function foo(){
a = 5
console.log(a);
var a;
}
foo();
console.log(a)答案是5,a is not defined
第4行代碼輸出5,第9行報錯。
這種情況就是變量提升只會提升到變量所在的 作用域的頂部,不會提升到父級作用域。
因此可以得出一個結論:變量提升只會將變量提升到自己所在的作用域的頂部
函數優先
既然用var和function的變量都有提升的功能,那如果同一個變量用這兩種都聲明會怎樣,好吧,看標題就知道了,函數優先。
具體看下代碼
foo();
var foo;
function foo(){
console.log(1)
}
foo = function(){
console.log(2)
}答案是1
這段代碼其實這樣子的
function foo(){
console.log(1)
}
foo();// 1
foo = function(){
console.log(2)
}仔細一看,var foo;沒了,沒錯,它被引擎忽略了,認為重復聲明所以把它拋棄了。
好,既然var聲明的變量比不了函數聲明,那就用函數聲明,多次聲明同個變量。
foo()
function foo(){
console.log(1);
}
foo()
function foo(){
console.log(2);
}
foo()
function foo(){
console.log(3);
}
foo()foo聲明了三次,調用了四次,每次調用的結果都是3,所以最后的函數聲明會覆蓋之前的函數聲明
但是var還想掙扎一下,覺得還是有必要證明自己的存在感的。
foo()
function foo(){
console.log(1);
}
var foo;
foo()
foo = function(){
console.log(2);
}
foo()
function foo(){
console.log(3);
}
foo()仔細看,中間那部分代碼改了,依次輸出3,3,2,2
雖然var foo被忽略了,但下面的函數還是有用的,這段代碼可以看成是這樣的
function foo(){
console.log(3);
}
foo();//3
foo();//3
foo = function(){
console.log(2);
}
foo();//2
foo();//2在普通塊內部聲明函數
之前是在作用域聲明函數,現在來塊里面聲明函數
function foo(){
console.log(b); // undefined
b(); //TypeError: b is not a function
var a = true;
if(a){
function b(){
console.log(2)
}
//下面這段代碼和上面的結果一樣
// var b = function(){
// console.log(2)
// }
}
//b() --> 這里會被執行
}
foo()從上面看上去,b是undefined,證明這個變量還是有的,只不過它并不是一個函數,這情況和用函數表達式差不多。
總結
1、提升分為函數聲明提升和變量聲明提升
2、聲明變量用var,聲明函數用function
3、變量提升會將變量提升到自己所在作用域的頂部
4、函數表達式不存在提升的機制
5、函數聲明和變量聲明同時聲明同一個標識符時,函數聲明優先
6、多個函數聲明同一個標識符時,最后一個聲明覆蓋先前的聲明
以上就是js中的變量提升機制的簡略介紹,當然詳細使用上面的不同還得要大家自己使用過才領會。如果想了解更多,歡迎關注億速云行業資訊頻道哦!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。