溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

js中的變量提升機(jī)制介紹

發(fā)布時(shí)間:2020-05-19 11:20:34 來(lái)源:億速云 閱讀:377 作者:小新 欄目:web開(kāi)發(fā)

今天小編給大家分享的是js中的變量提升機(jī)制介紹,相信很多人都不太了解,為了讓大家更加了解js中的變量提升機(jī)制,所以給大家總結(jié)了以下內(nèi)容,一起往下看吧。一定會(huì)有所收獲的哦。

變量提升

JavaScript的變量提升有兩種,用var聲明的變量以及用function聲明的變量。

用var聲明的變量

我們先來(lái)看下面這段代碼,a的值是多少

代碼1

console.log(a);

var a;

按照以往編程語(yǔ)言的思路來(lái)看,代碼自上而下運(yùn)行,按這種思路,會(huì)報(bào)錯(cuò),因?yàn)閳?zhí)行到第2行時(shí),變量a還沒(méi)有定義,所以會(huì)報(bào)錯(cuò)a is not defined

然而事實(shí)上答案是undefined

好,抱著疑惑,我們看下面的代碼

var a;
console.log(a);

我們發(fā)現(xiàn),這兩段代碼是一樣的,那么又有一個(gè)新的問(wèn)題,是不是有沒(méi)有var a都無(wú)所謂,它的答案始終是undefined,才造成了以為變量會(huì)提升的錯(cuò)覺(jué),于是我寫(xiě)了代碼3

代碼3

console.log(a);

好,它終于報(bào)錯(cuò)了,所以這證明了javaScript代碼并不是自上而下執(zhí)行的,至少?gòu)谋砻婵瓷厦媸沁@樣的。

于是我們?cè)倏创a4

代碼4

console.log(a);
var a = 2;

因?yàn)樽兞刻嵘铮源鸢甘?,然而事實(shí)上,它依然是undefined,why?

這時(shí)候我們有請(qǐng)編譯器這位負(fù)責(zé)語(yǔ)法分析及代碼生成等臟活累活的大佬。

編譯器在看到var a = 2;,它會(huì)將其看做兩個(gè)聲明,var a;和a = 2,第一個(gè)聲明在編譯階段進(jìn)行,第二個(gè)聲明會(huì)被原地等待執(zhí)行階段。

也就是說(shuō)上面代碼,會(huì)變成下面的這段代碼

var a;
console.log(a);
a = 2;

所以最終會(huì)是undefined

好,我在啰嗦一下,看這段代碼5

代碼5

a = 2;
var a;
console.log(a);

我想大家應(yīng)該已經(jīng)知道這段代碼執(zhí)行時(shí)的真正順序及其答案了,沒(méi)錯(cuò),答案是2,但我想說(shuō)的是把第2行給注釋掉,答案依然是2,但這個(gè)和變量提升沒(méi)啥關(guān)系了,是嚴(yán)格模式與非嚴(yán)格模式的鍋,在非嚴(yán)格模式下允許開(kāi)發(fā)者可以不使用聲明變量的關(guān)鍵字,但在嚴(yán)格模式下是不可以的,它會(huì)報(bào)錯(cuò)的。

用function聲明的變量

與var一樣,function聲明的變量依然會(huì)提升。

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)
}

它報(bào)錯(cuò)了,log is not a function,從這里我們可以看出,這種函數(shù)表達(dá)式是不會(huì)被提升的,只有函數(shù)聲明才會(huì)被提升,試著在最前面新增一行代碼console.log(log),會(huì)先輸出undefined。

所以這里的真正順序是

var log;
log(); //這時(shí)候只是聲明了log這個(gè)變量,并不是函數(shù),卻用函數(shù)的方法調(diào)用它,所以會(huì)報(bào)錯(cuò),說(shuō)這不是一個(gè)函數(shù)。
log = function(mes){
  console.log(mes)
}

在function里用var聲明變量

我們雖然知道,var聲明的變量會(huì)提升,但并不知道會(huì)提升到哪個(gè)程度。

在此之前來(lái)看一段代碼

var a = 4;

function foo(){
  var a = 5;
  console.log(a);

}
foo();

console.log(a)

答案是5,4,先輸出5,再輸出4。

用var聲明的變量是有函數(shù)作用域的,所以foo里的a和foo外面的a沒(méi)有任何關(guān)系,這種情況正是我想要的。

再改下代碼

function foo(){
  a = 5
  console.log(a);
  var a;
}
foo();

console.log(a)

答案是5,a is not defined

第4行代碼輸出5,第9行報(bào)錯(cuò)。

這種情況就是變量提升只會(huì)提升到變量所在的 作用域的頂部,不會(huì)提升到父級(jí)作用域。

因此可以得出一個(gè)結(jié)論:變量提升只會(huì)將變量提升到自己所在的作用域的頂部

函數(shù)優(yōu)先

既然用var和function的變量都有提升的功能,那如果同一個(gè)變量用這兩種都聲明會(huì)怎樣,好吧,看標(biāo)題就知道了,函數(shù)優(yōu)先。

具體看下代碼

foo();

var foo;

function foo(){
  console.log(1)
}

foo = function(){
  console.log(2)
}

答案是1

這段代碼其實(shí)這樣子的

function foo(){
  console.log(1)
}

foo();// 1

foo = function(){
  console.log(2)
}

仔細(xì)一看,var foo;沒(méi)了,沒(méi)錯(cuò),它被引擎忽略了,認(rèn)為重復(fù)聲明所以把它拋棄了。

好,既然var聲明的變量比不了函數(shù)聲明,那就用函數(shù)聲明,多次聲明同個(gè)變量。

foo()
function foo(){
  console.log(1);
}
foo()
function foo(){
  console.log(2);
}
foo()
function foo(){
  console.log(3);
}

foo()

foo聲明了三次,調(diào)用了四次,每次調(diào)用的結(jié)果都是3,所以最后的函數(shù)聲明會(huì)覆蓋之前的函數(shù)聲明

但是var還想掙扎一下,覺(jué)得還是有必要證明自己的存在感的。

foo()
function foo(){
  console.log(1);
}
var foo;
foo()
foo = function(){
  console.log(2);
}
foo()
function foo(){
  console.log(3);
}

foo()

仔細(xì)看,中間那部分代碼改了,依次輸出3,3,2,2

雖然var foo被忽略了,但下面的函數(shù)還是有用的,這段代碼可以看成是這樣的

function foo(){
  console.log(3);
}

foo();//3
foo();//3
foo = function(){
  console.log(2);
}
foo();//2
foo();//2

在普通塊內(nèi)部聲明函數(shù)

之前是在作用域聲明函數(shù),現(xiàn)在來(lái)塊里面聲明函數(shù)

function foo(){

  console.log(b); // undefined
  b(); //TypeError: b is not a function

  var a = true;

  if(a){
    function b(){
      console.log(2)
    }
    //下面這段代碼和上面的結(jié)果一樣
    // var b = function(){
 //      console.log(2)
 //    }
  }
  //b() --> 這里會(huì)被執(zhí)行

}

foo()

從上面看上去,b是undefined,證明這個(gè)變量還是有的,只不過(guò)它并不是一個(gè)函數(shù),這情況和用函數(shù)表達(dá)式差不多。

總結(jié)

1、提升分為函數(shù)聲明提升和變量聲明提升

2、聲明變量用var,聲明函數(shù)用function

3、變量提升會(huì)將變量提升到自己所在作用域的頂部

4、函數(shù)表達(dá)式不存在提升的機(jī)制

5、函數(shù)聲明和變量聲明同時(shí)聲明同一個(gè)標(biāo)識(shí)符時(shí),函數(shù)聲明優(yōu)先

6、多個(gè)函數(shù)聲明同一個(gè)標(biāo)識(shí)符時(shí),最后一個(gè)聲明覆蓋先前的聲明

以上就是js中的變量提升機(jī)制的簡(jiǎn)略介紹,當(dāng)然詳細(xì)使用上面的不同還得要大家自己使用過(guò)才領(lǐng)會(huì)。如果想了解更多,歡迎關(guān)注億速云行業(yè)資訊頻道哦!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

js
AI