摘要:最近在上看到一篇關(guān)于變量提升的文章,原文在此。對(duì)于剛?cè)腴T的開發(fā)者時(shí)常難以理解變量方法提升的獨(dú)特行為。接下來我們要談?wù)摚暶?,那么先了解變量提升就顯得更為重要了。在進(jìn)入作用域和不能訪問的這段時(shí)間,我們稱為暫時(shí)性死區(qū)。
最近在Medium上看到一篇關(guān)于“變量提升”的文章,原文在此:《A guide to JavaScript variable hoisting with let and const》。為了培養(yǎng)自己看英文文檔習(xí)慣且看懂的需要,就翻譯一下。談不上精確,歡迎指正。
對(duì)于剛?cè)腴T的JavaScript開發(fā)者時(shí)常難以理解“變量/方法”提升(hoisting)的獨(dú)特行為。
接下來我們要談?wù)搗ar,let,const聲明,那么先了解變量提升就顯得更為重要了。那就開始吧。
JavaScript引擎用“var”處理所有變量聲明,不管在哪里聲明,最后都會(huì)在函數(shù)作用域頂端(如果在函數(shù)內(nèi)部聲明)或則在全局作用域頂端(在函數(shù)外部聲明)。這就是“提升”。
因此變量實(shí)際上可能在聲明它之前就已經(jīng)被引擎獲得了。
在實(shí)際操作中看看效果..
// OUTPUT : undefined console.log(shape); var shape = square; // OUTPUT : square console.log(shape);
如果你來自C語言,你認(rèn)為在第一個(gè)console.log那里就會(huì)拋出變量未定義的錯(cuò)誤。但JavaScript解釋器預(yù)感和“提升”所有變量聲明到作用域頂端,并且在那進(jìn)行初始化。
下面演示實(shí)際發(fā)生了什么:
//declaration getting hoisted at the top var shape; // OUTPUT : undefined console.log(shape); shape = square; // OUTPUT : square console.log(shape);
另一個(gè)例子是用函數(shù)作用域來更清楚的展示:
function getShape(condition) { // shape exists here with a value of undefined // OUTPUT : undefined console.log(shape); if (condition) { var shape = square; // some other code return shape; } else { // shape exists here with a value of undefined return false; } }
上面的例子可以看出shape聲明被提升到了“getShape”函數(shù)作用域的頂端。這是因?yàn)椤癷f/else” 不能像其他語言那樣,創(chuàng)建局部作用域。在JavaScript里,函數(shù)作用域?qū)嶋H上就是局部作用域了。因此,“shape”可以在if塊之外,函數(shù)作用域內(nèi)任意訪問,且值為“undefined”。
JavaScript的這個(gè)默認(rèn)行為,既是優(yōu)點(diǎn),又是缺點(diǎn)。沒有完全掌握的話,會(huì)給我們的代碼帶來細(xì)微且危險(xiǎn)的bugs。
進(jìn)入塊級(jí)作用域!
ES6 引入了塊級(jí)作用域,這讓開發(fā)者對(duì)變量有了更多的控制,且讓變量有靈活的生命周期。
塊級(jí)聲明在塊級(jí)/詞法作用域里面聲明,他們?cè)凇皗}”中被創(chuàng)建。
“l(fā)et”語法跟“var”相似,只是用“l(fā)et”標(biāo)識(shí)符來替換“var”標(biāo)識(shí)符進(jìn)行變量聲明,其作用域范圍僅僅在聲明的那個(gè)代碼塊。
let聲明放在塊的頂端,因此只能在那個(gè)塊級(jí)作用域中訪問。
舉例:
function getShape(condition) { // shape doesn"t exist here // console.log(shape); ReferenceError: shape is not defined if (condition) { let shape = square; // some other code return shape; } else { // shape doesn"t exist here as well return false; } }
注意shape只存在if塊中,當(dāng)在if塊外面訪問時(shí)會(huì)拋出一個(gè)錯(cuò)誤,而不是象我們之前用var聲明那樣輸出“undefined”。
提示:在同一個(gè)作用域內(nèi),如果已經(jīng)使用var標(biāo)識(shí)符聲明了變量,同時(shí)又用let標(biāo)識(shí)符聲明同名變量時(shí)會(huì)拋出錯(cuò)誤。
但是,如果在let聲明的變量作用域外,聲明同名變量是不會(huì)報(bào)錯(cuò)的。(這種情況也同樣適用于我們即將談?wù)摰腸onst聲明。)
舉例:
var shape = square; let shape = rectangle; // SyntaxError: Identifier "shape" has already been declared
和
var shape = square; if (condition) { // doesn"t throw an error let shape = rectangle; // more code } // No errorconst聲明
const聲明語法與let和var相似,生命周期與let相同,但你還要注意一些規(guī)則。
用const聲明的變量將像常量看待,因此它們的值在定義后是不可以修改的。由于這樣,每個(gè)const變量都必須在聲明的同時(shí)進(jìn)行初始化。
舉例:
// valid const shape = triangle; // syntax error: missing initialization const color; // TypeError: Assignment to constant variable shape = square;
然而,這個(gè)規(guī)則在聲明對(duì)象時(shí)有點(diǎn)不同。對(duì)象屬性的值可以被修改!
const shape = { name: triangle, sides: 3 } // WORKS shape.name = square; shape.sides = 4; // SyntaxError: Invalid shorthand property initializer shape = { name: hexagon, sides: 6 }
在上面的例子中,我們可以看到shape對(duì)象屬性的值可以被修改,因?yàn)槲覀冎桓淖僺hape包含的,而不是它本身。
我們可以總結(jié)說,const可以防止整個(gè)綁定的修改,而不是綁定的值。
提示:屬性可以改變。所以對(duì)于真正不可變的,請(qǐng)使用Immutable.js或Mori。
我們都知道,如果我們?cè)谑褂胠et,const聲明定義的變量之前就使用這些變量,會(huì)拋出ReferenceError錯(cuò)誤。 在進(jìn)入作用域和不能訪問的這段時(shí)間,我們稱為暫時(shí)性死區(qū)。
提示:“暫時(shí)性死區(qū)”不是ECMAScript規(guī)范里的正式定義,它只是在程序員中廣為流行而已。
我個(gè)人推薦總是使用const,因?yàn)樗蝗菀壮鲥e(cuò)。我還沒遇到需要使用var的情況。
作為基本規(guī)則,只在循環(huán)計(jì)數(shù)器中,或則你真的需要給變量從新賦值時(shí)用let。其他地方,用const。我已經(jīng)放棄使用循環(huán),轉(zhuǎn)而選擇使用filter,map,reduce等方法。你也應(yīng)該如此。
后記,此作者還有一篇關(guān)于方法提升的文章,到時(shí)候在搬來。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/90355.html
摘要:函數(shù)提升在里有兩種方式創(chuàng)建函數(shù),通過函數(shù)聲明和函數(shù)表達(dá)式。函數(shù)聲明用指定的參數(shù)來定義函數(shù)。提示不要在中進(jìn)行函數(shù)聲明。問題輸出兩個(gè)都是用函數(shù)聲明的函數(shù),將被提升到的局部作用域頂端。函數(shù)本身將作為函數(shù)聲明在全局范圍內(nèi)提升。 作者關(guān)于提升的話題,總共有兩篇。(后來又有一個(gè)討論篇),再次搬過來。水平有限,如果翻譯的不準(zhǔn)確請(qǐng)包涵,并去看原文。下面開始: 這是我之前的關(guān)于提升的文章,標(biāo)題為《用le...
摘要:理解執(zhí)行上下文和執(zhí)行堆棧對(duì)于理解的其它概念如提升,范圍和閉包至關(guān)重要。正確地理解執(zhí)行上下文和執(zhí)行堆棧將幫助你更好地使用開發(fā)應(yīng)用。引擎執(zhí)行位于執(zhí)行堆棧頂部的方法。當(dāng)調(diào)用時(shí),為該函數(shù)創(chuàng)建一個(gè)新的執(zhí)行上下文,并且把它推入到當(dāng)前執(zhí)行堆棧。 By Sukhjinder Arora | Aug 28, 2018 原文 如果你是或者你想要成為一名js開發(fā)者,那么你必須了解js程序內(nèi)部的運(yùn)作。理解執(zhí)行...
摘要:外層作用域不報(bào)錯(cuò)正常輸出塊級(jí)作用域與函數(shù)聲明規(guī)定,函數(shù)只能在頂層作用域和函數(shù)作用域之中聲明,不能在塊級(jí)作用域聲明。規(guī)定,塊級(jí)作用域之中,函數(shù)聲明語句的行為類似于,在塊級(jí)作用域之外不可引用。同時(shí),函數(shù)聲明還會(huì)提升到所在的塊級(jí)作用域的頭部。 前言:最近開始看阮一峰老師的《ECMAScript 6 入門》(以下簡稱原...
摘要:如果是你是高級(jí)或者初級(jí)開發(fā)人員,了解它的基本概念非常重要。由于是基本類型,因此的值等于的值,并且可以認(rèn)為此時(shí)與完全不同。展開運(yùn)算符可用于提取數(shù)組的各個(gè)元素。函數(shù)本身返回從數(shù)組中刪除的項(xiàng)。如果未指定結(jié)束位置,則返回?cái)?shù)組的其余部分。 譯者:前端小智 原文:hackernoon.com/12-javascri… JavaScript 是一種復(fù)雜的語言。如果是你是高級(jí)或者初級(jí) JavaScript...
摘要:中的所有對(duì)象都來自父的構(gòu)造函數(shù)。不同于數(shù)組的原型方法例如和只能被數(shù)組實(shí)例使用,對(duì)象方法直接來自構(gòu)造函數(shù),并使用對(duì)象實(shí)例作為參數(shù)。這稱為靜態(tài)方法。創(chuàng)建對(duì)象的鍵值對(duì)的嵌套數(shù)組??捎糜诖_定對(duì)象是否已凍結(jié),并返回布爾值。 原文:How To Use Object Methods in JavaScript作者:Tania Rascia譯者:博軒 介紹 JavaScript 中,對(duì)象是 鍵/值 ...
閱讀 3616·2021-11-24 10:22
閱讀 3686·2021-11-22 09:34
閱讀 2480·2021-11-15 11:39
閱讀 1528·2021-10-14 09:42
閱讀 3662·2021-10-08 10:04
閱讀 1553·2019-08-30 15:52
閱讀 847·2019-08-30 13:49
閱讀 3015·2019-08-30 11:21