摘要:對(duì)于大多數(shù)開發(fā)者來說,變量提升可以說是一個(gè)非常常見的問題,但是可能很多人對(duì)其不是特別的了解。如果說擁有和一樣的變量提升效果的話,那么應(yīng)該是輸出。而和它們的變量提升的效果是一樣的,也都存在著臨死性死區(qū)的概念。
對(duì)于大多數(shù)js開發(fā)者來說,變量提升可以說是一個(gè)非常常見的問題,但是可能很多人對(duì)其不是特別的了解。所以在此,我想來講一講。
先從一個(gè)簡(jiǎn)單的例子來入門:
a = 2; var a; console.log(a);
你覺得以上的代碼會(huì)輸出什么?是輸出undefined嗎?如果是按照程序的自上而下執(zhí)行的話,那么這一段代碼確實(shí)是輸出undefined,因?yàn)関ar a語(yǔ)句把a(bǔ) = 2的語(yǔ)句給覆蓋了。然而,javascript并不是嚴(yán)格的自上而下執(zhí)行的語(yǔ)言。
這一段代碼的輸出結(jié)果是2,是不是感到很意外?為什么會(huì)這樣呢?這個(gè)問題的關(guān)鍵就在于變量提升(hoisting)。它會(huì)將當(dāng)前作用域的所有變量的聲明提升到程序的頂部,因此上面的代碼其實(shí)等價(jià)于以下代碼。這樣是不是就很簡(jiǎn)單明了了。
var a; a = 2; console.log(a);
那么接下來,我們?cè)賮砜催@個(gè)例子。
console.log(a); var a = 2;
你覺得以上的代碼會(huì)輸出什么?是直接報(bào)ReferenceError嗎?還是輸出2呢?
其實(shí)以上代碼會(huì)輸出undefined。為什么呢?我們之前說過,js會(huì)將變量的聲明提升到頂部,可是賦值語(yǔ)句并不會(huì)提升。所以對(duì)于js來說,其實(shí)var a = 2是分為兩步的:
var a;
a = 2;
而js只會(huì)將第一步提升到頂部,所以上面的語(yǔ)句等價(jià)于:
var a; console.log(a); a = 2;為什么有變量提升
那么為什么會(huì)出現(xiàn)變量提升這個(gè)現(xiàn)象呢?
js和其他語(yǔ)言一樣,都要經(jīng)歷編譯和執(zhí)行階段。而js在編譯階段的時(shí)候,會(huì)搜集所有的變量聲明并且提前聲明變量,而不會(huì)改變其他語(yǔ)句的順序,因此,在編譯階段的時(shí)候,第一步就已經(jīng)執(zhí)行了,而第二步則是在執(zhí)行階段執(zhí)行到該語(yǔ)句的時(shí)候才執(zhí)行。
變量聲明js的變量聲明其實(shí)大體上可以分為三種:var聲明、let與const聲明和函數(shù)聲明。
函數(shù)聲明與其他聲明一起出現(xiàn)的時(shí)候,就可能會(huì)引起一些困擾。我們來看下面的例子。
foo(); function foo() { console.log("foo"); } var foo = 2;
你覺得上面會(huì)輸出什么?TypeError嗎?還是輸出foo呢?想一想再接著往下看。
當(dāng)當(dāng)當(dāng)當(dāng),其實(shí)最后輸出的結(jié)果是foo。這就引出了我們的問題了,當(dāng)函數(shù)聲明與其他聲明一起出現(xiàn)的時(shí)候,是以誰(shuí)為準(zhǔn)呢?答案就是,函數(shù)聲明高于一切,畢竟函數(shù)是js的第一公民。
那么,下面的例子呢?
foo(); function foo() { console.log("1"); } function foo() { console.log("2"); }
當(dāng)出現(xiàn)多個(gè)函數(shù)聲明,那怎么辦呢?
上面這個(gè)代碼輸出結(jié)果為2。因?yàn)橛卸鄠€(gè)函數(shù)聲明的時(shí)候,是由最后面的函數(shù)聲明來替代前面的。
想必經(jīng)歷了以上的例子,你應(yīng)該已經(jīng)對(duì)變量聲明已經(jīng)有一定的了解了。那么我再來出一道題目來測(cè)試下。
foo(); var foo = function() { console.log("foo"); }
這道題目是不是非常簡(jiǎn)單???這道題和上面的第二道例子其實(shí)是一樣的。var foo = function() {}這種格式我們叫做函數(shù)表達(dá)式。
它其實(shí)也是分為兩部分,一部分是var foo,而一部分是foo = function() {},參照例2,我們可以知道,這道題的結(jié)果應(yīng)該是報(bào)了TypeError(因?yàn)閒oo聲明但未賦值,因此foo是undefined)。
上面我們提到了var聲明,函數(shù)聲明,那么接下來我們來講講let和const聲明。
let和const其實(shí)也是有函數(shù)提升的概念,不過它們會(huì)比較特殊,與var不一樣,它們存在一個(gè)臨死性死區(qū)的概念。我們可以通過一個(gè)例子來體現(xiàn)這一點(diǎn)。
var a = 2; function test() { console.log(a); let a = 5; } test();
你覺得上面的代碼會(huì)輸出什么呢?是輸出2,還是undefined呢?
如果說,let沒有變量提升的效果的話,那么應(yīng)該是輸出2。如果說let擁有和var一樣的變量提升效果的話,那么應(yīng)該是輸出undefined。然而,其實(shí)上面的代碼是會(huì)報(bào)錯(cuò)的。會(huì)報(bào)"ReferenceError: a is not defined"錯(cuò)誤。那么為什么呢?
這其實(shí)就是我說的,let雖然具有變量提升的功能,但是它又與var不一樣,它具有一個(gè)臨死性死區(qū)的概念。
臨死性死區(qū)其實(shí)就是說,a我已經(jīng)聲明了,可是在沒有到它賦值的時(shí)候,你都不能使用這個(gè)變量,不然就會(huì)報(bào)錯(cuò)。所以該當(dāng)前作用域開始,一直到let a = 5為止這整一塊,都是a變量的臨死性死區(qū),你不能使用它。
而const和let它們的變量提升的效果是一樣的,也都存在著臨死性死區(qū)的概念。
總結(jié)那么接下來我們來總結(jié)一下。
js會(huì)將變量的聲明提升到j(luò)s頂部執(zhí)行,因此對(duì)于這種語(yǔ)句:var a = 2;其實(shí)上js會(huì)將其分為var a;和a = 2;兩部分,并且將var a這一步提升到頂部執(zhí)行。
變量提升的本質(zhì)其實(shí)是由于js引擎在編譯的時(shí)候,就將所有的變量聲明了,因此在執(zhí)行的時(shí)候,所有的變量都已經(jīng)完成聲明。
當(dāng)有多個(gè)同名變量聲明的時(shí)候,函數(shù)聲明會(huì)覆蓋其他的聲明。如果有多個(gè)函數(shù)聲明,則是由最后的一個(gè)函數(shù)聲明覆蓋之前所有的聲明。
let和const都具有變量提升的效果,但是它們都具有臨死性死區(qū),從作用域開始部門,一直到變量的聲明語(yǔ)句這整一塊,你都不能使用該變量。
以上,就是本文的內(nèi)容。覺得有用的話麻煩點(diǎn)個(gè)贊,嘻嘻。
本文地址在->本人博客地址, 歡迎給個(gè) start 或 follow
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98942.html
摘要:忍者級(jí)別的函數(shù)操作對(duì)于什么是匿名函數(shù),這里就不做過多介紹了。我們需要知道的是,對(duì)于而言,匿名函數(shù)是一個(gè)很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個(gè)供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果...
摘要:自我學(xué)習(xí)目前有成千上萬的年輕人在學(xué)習(xí)和開發(fā),希望獲得一份工作。知道的綁定規(guī)則。知道和原型屬性是什么以及它們的作用。高階函數(shù)了解函數(shù)是中的一級(jí)對(duì)象,這意味著什么知道從另一個(gè)函數(shù)返回函數(shù)是完全合法的。了解閉包和高階函數(shù)允許我們使用的情況。 翻譯原文出處:10 JavaScript concepts you need to know for interviews 之前不是鬧得沸沸揚(yáng)揚(yáng)的大漠窮...
摘要:全局對(duì)象在程序任何地方都能訪問到的對(duì)象,在瀏覽器中是變量指向在中是什么外部環(huán)境暫時(shí)不講。函數(shù)聲明直接提前。執(zhí)行過程,函數(shù)執(zhí)行和銷毀過程。變量預(yù)解析,賦值外部環(huán)境之間的關(guān)系。如果做不對(duì),繼續(xù)找,直到合格。 當(dāng)程序在瀏覽器中運(yùn)行的時(shí)候,js引擎會(huì)產(chǎn)生三個(gè)東西。 showImg(https://segmentfault.com/img/bVMjv4?w=890&h=422);1.全局對(duì)象 ...
摘要:月初,一個(gè)和我關(guān)系不錯(cuò)的阿里朋友,在內(nèi)網(wǎng)看到一個(gè)開發(fā)專家的崗位,挺適合我,便問我有沒有興趣。正式開始電面正式開始,下文中阿里面試官簡(jiǎn)稱。晚上點(diǎn)左右,接到阿里影業(yè)的來電,我趕緊帶好耳機(jī)接起電話。 讀完本文需要 3 分鐘。 首先,跟大家說聲抱歉,年后實(shí)在是太忙,帶娃、錄視頻、換工作,大堆事情擠在一起,一不小心就斷更了 4 個(gè)月,實(shí)在是對(duì)不起一直以來支持我的朋友們。 從今天開始,我盡量堅(jiān)持...
閱讀 2078·2023-04-25 17:48
閱讀 3590·2021-09-22 15:37
閱讀 2941·2021-09-22 15:36
閱讀 6008·2021-09-22 15:06
閱讀 1644·2019-08-30 15:53
閱讀 1431·2019-08-30 15:52
閱讀 716·2019-08-30 13:48
閱讀 1126·2019-08-30 12:44