摘要:代碼在執(zhí)行時并不完全是由上到下一行一行執(zhí)行的,由此產(chǎn)生了一個提升的問題。第二個賦值聲明會被留在原地等待執(zhí)行階段??梢缘弥瘮?shù)聲明提升的優(yōu)先權(quán)大于普通變量聲明。
JavaScript代碼在執(zhí)行時并不完全是由上到下一行一行執(zhí)行的,由此產(chǎn)生了一個提升的問題。
什么是提升可以簡單理解為:聲明(變量和函數(shù))都會被“移動”到各自作用域的最頂端,這個過程被稱為提升。
具體例子看提升下面兩個例子a會log什么出來呢?
a = 233; var a; console.log(a)
console.log(a); var a = 233;
“看起來”第一個例子應(yīng)該log出undefined,第二個例子變量a在使用前沒有先進行聲明,因此會拋出ReferenceError異常。但實際上,第一個例子a輸出233,第二個例子a輸出undefined。
為什么?
在知道為什么之前有必要了解:JavaScript雖然是解釋型語言,但在解釋JavaScript代碼之前首先對其進行編譯的。編譯階段中的一部分工作就是找到所有的聲明,并用合適的作用域?qū)⑺鼈冴P(guān)聯(lián)起來。
變量和函數(shù)在內(nèi)的所有聲明都會在任何代碼被執(zhí)行前首先被處理。
var a = 233;
上面的聲明看起來是一個聲明,而對于JavaScript而言實際上這是兩個聲明:var a;和a = 233;。第一個定義聲明是在編譯階段進行的。第二個賦值聲明會被留在原地等待執(zhí)行階段。
看回前面兩個例子,第一個例子的代碼會被這樣處理:
var a; a = 233; console.log(a);
第二個例子:
var a; console.log(a); a = 233;
注意:只有聲明本身會被提升,而賦值或其他運行邏輯會留在原地 。
函數(shù)聲明與函數(shù)表達式第一個例子:
foo(); function foo() { console.log(a); // undefined var a = 233; }
函數(shù)foo可以正常執(zhí)行。
第二個例子:
foo(); // TypeError var foo = function bar() { // ... }
報錯:Uncaught TypeError: foo is not a function
由此可以看到:函數(shù)聲明會被提升,但是函數(shù)表達式卻不會被提升。
第三個例子:
foo(); // TypeError bar(); // ReferenceError var foo = function bar() { // ... };
這段代碼經(jīng)過提升后,可以理解為以下形式:
var foo; foo(); // TypeError bar(); // ReferenceError foo = function() { var bar = ...self... // ... };
由此可見:具名的函數(shù)表達式,名稱標識符在賦值之前也無法在所在作用域中使用。
函數(shù)優(yōu)先既然函數(shù)聲明和變量聲明都會被提升,那么問題來了,重復聲明的代碼中的優(yōu)先級是怎樣的,是函數(shù)聲明被提升還是變量聲明被提升?
繼續(xù)驗證:
foo(); // 1 var foo; function foo() { console.log( 1 ); } foo = function() { console.log( 2 ); }
var foo盡管出現(xiàn)在 function foo()...的聲明之前,但它是重復的聲明而被忽略,因為函數(shù)聲明會被提升到普通變量之前??梢缘弥汉瘮?shù)聲明提升的優(yōu)先權(quán)大于普通變量聲明。
盡管重復的var聲明會被忽略掉,但出現(xiàn)在后面的函數(shù)聲明還是可以覆蓋前面的:
foo(); // 3 function foo() { console.log( 1 ); } var foo = function() { console.log( 2 ); }; function foo() { console.log( 3 ); }ES6中的變量聲明
ES6新增了let、const聲明,它們會存在一個暫時性死區(qū)(TDZ),表現(xiàn)出的情況會有所不同,具體可以參考:let, const
總結(jié)var變量聲明和函數(shù)聲明存在提升
函數(shù)表達式不會被提升
函數(shù)聲明提升的優(yōu)先權(quán)大于普通變量聲明
let, const由于存在暫時性死區(qū),表現(xiàn)出的情況和var聲明有所不同
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/90180.html
摘要:可以發(fā)送通知消息以再次吸引用戶并留住他們。在即時通訊等使用情形中,一條消息可將最多的有效負載傳送至客戶端應(yīng)用。瀏覽器的的消息推送主要依賴,服務(wù)端消息推送傳遞到,然后再由推送到客戶端。 引言 Progressive Web App, 簡稱 PWA,是提升 Web App 的體驗的一種新方法,能給用戶原生應(yīng)用的體驗。Service Worker 是 PWA 中的重要一部分。Service ...
摘要:特點是塊級作用域的特點得到明顯的體現(xiàn)再看一個中的循環(huán)變量泄露為全局變量很明顯成了全局變量。本人目前了解的還不夠深比如中添加一個新的詞匯暫時性死區(qū),簡稱。 (個人理解ES6就是對ES5的BUG修改和升級)廢話不多說今天要探討的是 var與letECMAScript 6 入門 作者:阮一峰 下面是個人總結(jié):let不允許在相同作用域內(nèi),重復聲明同一個變量。let 特點是塊級作用域 先來看一...
摘要:一前言的垃圾回收機制使用垃圾回收機制來自動管理內(nèi)存。垃圾回收器只會針對新生代內(nèi)存區(qū)老生代指針區(qū)以及老生代數(shù)據(jù)區(qū)進行垃圾回收。分別對新生代和老生代使用不同的垃圾回收算法來提升垃圾回收的效率。 V8 實現(xiàn)了準確式 GC,GC 算法采用了分代式垃圾回收機制。因此,V8 將內(nèi)存(堆)分為新生代和老生代兩部分。 一、前言 V8的垃圾回收機制:JavaScript使用垃圾回收機制來自動管理內(nèi)存。垃...
摘要:本文是淺析微信支付系列文章的第十一篇,主要講解支付驗收示例和驗收指引。為保證商戶接入質(zhì)量,提升交易安全及用戶體驗,微信支付的合作服務(wù)商在正式上線交易前,必須先根據(jù)本文指引完成驗收。 本文是【淺析微信支付】系列文章的第十一篇,主要講解支付驗收示例和驗收指引。 淺析微信支付系列已經(jīng)更新十一篇了喲~,沒有看過的朋友們可以看一下。 淺析微信支付:如何使用沙箱環(huán)境測試 淺析微信支付:下載對賬單...
閱讀 1585·2021-09-22 15:52
閱讀 3495·2021-09-22 14:59
閱讀 2926·2021-09-02 15:12
閱讀 1008·2021-08-20 09:35
閱讀 1602·2019-08-30 14:09
閱讀 2737·2019-08-30 13:56
閱讀 1687·2019-08-26 18:27
閱讀 3390·2019-08-26 13:37