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