詳解JavaScript?中的變量聲明與賦值
在計算機(jī)編程中,使用名稱(或標(biāo)識符)來表示值是最基本的技術(shù)之一。將名稱與值綁定為我們提供了一種在程序中引用值并利用它們的方式。當(dāng)涉及到綁定名稱與值時,我們通常稱之為將值賦給變量。術(shù)語“變量”暗示了新的值可以被賦給它,這意味著與變量關(guān)聯(lián)的值在程序執(zhí)行過程中可能會改變。如果一個值被永久地分配給一個名稱,那么該名稱可以被視為常量而不是變量。
在 JavaScript 中使用變量或常量之前,必須先進(jìn)行聲明。在 ES6 版本及更高版本的 JavaScript 中,可以使用 let
和 const
關(guān)鍵字來實(shí)現(xiàn)這一點(diǎn),我們將在稍后介紹。在 ES6 之前,變量使用 var
關(guān)鍵字進(jìn)行聲明。
1. 使用 let 和 const 進(jìn)行聲明。
在現(xiàn)代 JavaScript(ES6 及更高版本)中,變量使用 let
關(guān)鍵字進(jìn)行聲明:
let i; let sum;
也可以在單個 let
語句中聲明多個變量:
let i, sum;
在聲明時,最好將初始值賦給變量(如果可能的話):
let message = "hello"; let i = 0, j = 0, k = 0; // 初始化語句可以使用先前聲明的變量 let x = 2, y = x * x;
如果在 let
語句中沒有提供初始值,變量仍將被聲明,但其值將是 undefined
,直到它被賦值。要聲明常量而不是變量,請使用 const
關(guān)鍵字而不是 let
。const
類似于 let
,但關(guān)鍵區(qū)別在于常量在聲明時必須進(jìn)行初始化:
// 哈勃常數(shù)(km/s/Mpc) const H0 = 74; // 真空中的光速(km/s) const C = 299792.458; // 天文單位:地球和太陽之間的平均距離(km) const AU = 1.496E8;
正如名稱所示,常量的值不能被更改,嘗試重新分配常量會導(dǎo)致 TypeError
。聲明常量的通用(盡管不是普遍的)約定是使用大寫字母,例如 H0
或 HTTP_NOT_FOUND
,以將它們與變量區(qū)分開。
何時使用 const
。
在使用 const
關(guān)鍵字方面存在兩種觀點(diǎn)。一個觀點(diǎn)是僅在預(yù)期值不會更改的情況下使用 const
,例如物理常數(shù)、程序版本號或用于識別文件類型的字節(jié)順序標(biāo)記。另一個觀點(diǎn)認(rèn)為,在程序中,許多所謂的變量實(shí)際上在運(yùn)行時并不會改變。因此,建議是使用 const
來聲明所有變量,僅在發(fā)現(xiàn)需要允許它們的值發(fā)生變化時將其切換為 let
。這種方法有助于避免意外的變量修改,從而導(dǎo)致錯誤。
在第一種情況下,const
僅用于必須保持恒定的值。在第二種情況下,const
用于任何不會更改的值。就個人而言,在編寫代碼時,我更傾向于前一種方法。
JavaScript 中的循環(huán)結(jié)構(gòu):for
、for/in
和 for/of
循環(huán)。
在 JavaScript 中,循環(huán)結(jié)構(gòu)(如 for
、for/in
和 for/of
循環(huán))包括一個在循環(huán)的每次迭代中獲取新值的循環(huán)變量。JavaScript 允許在循環(huán)語法中聲明這個循環(huán)變量,這是 let
的另一個常見用例:
for (let i = 0, len = data.length; i < len; i++) console.log(data[i]); for (let datum of data) console.log(datum); for (let property in object) console.log(property);
雖然可能看起來有點(diǎn)不尋常,但也可以在 for/in
和 for/of
循環(huán)中使用 const
來聲明循環(huán)的“變量”,只要它們在循環(huán)體內(nèi)部不被重新賦值。在這種情況下,const
聲明表示循環(huán)變量的值在每次迭代中都是恒定的:
for (const datum of data) console.log(datum); for (const property in object) console.log(property);
變量和常量的作用域。
變量的作用域是指在源代碼中定義變量的區(qū)域。使用 let
和 const
聲明的變量和常量具有塊級作用域。這意味著它們僅在 let
或 const
語句的代碼塊內(nèi)部定義。JavaScript 類和函數(shù)的函數(shù)體被視為代碼塊,同樣,if/else
語句的語句體和 while
、for
循環(huán)的循環(huán)體也被視為代碼塊。簡單來說,如果變量或常量聲明在一對花括號內(nèi)部,那么這些花括號限制了變量或常量定義的代碼區(qū)域(當(dāng)然,在引用這些變量或常量之前的代碼行中引用在 let
或 const
語句中聲明它們是無效的)。作為 for
、for/in
或 for/of
循環(huán)的一部分聲明的變量和常量的作用域僅限于循環(huán)體, 即使循環(huán)聲明位于花括號外部。
如果聲明發(fā)生在頂層,在任何代碼塊之外,它被稱為全局變量或常量,并具有全局作用域。在 Node 和客戶端 JavaScript 模塊中,全局變量的作用域由聲明它們的文件決定。但是,在傳統(tǒng)的客戶端 JavaScript 中,全局變量的作用域由聲明它們的 HTML 文檔決定。換句話說,如果 <script>
標(biāo)簽聲明了全局變量或常量,那么該變量或常量將在同一文檔中的任何 <script>
元素中定義(或者至少在所有在執(zhí)行 let
和 const
語句之后執(zhí)行的腳本中定義)。
重新聲明。
在同一作用域內(nèi)多次使用 let
或 const
語句聲明相同名稱是語法錯誤。但是,在嵌套作用域中聲明相同名稱的變量是允許的(盡管通常建議避免這種情況):
// 將 x 聲明為全局常量 const x = 1; if (x === 1) { // 在同一代碼塊中,x 可以引用不同的值 let x = 2; // 輸出 2 console.log(x); } // 輸出 1:現(xiàn)在回到全局作用域 console.log(x); // 錯誤!重新聲明 x 會導(dǎo)致語法錯誤 let x = 3;
聲明和數(shù)據(jù)類型。
如果您有使用靜態(tài)類型語言(例如 C 或 Java)的經(jīng)驗(yàn),可能會認(rèn)為變量聲明的主要目的是指定變量可以保存的數(shù)據(jù)類型。然而,我們還看到,在 JavaScript 中,變量聲明并不與值的數(shù)據(jù)類型相關(guān)聯(lián)。JavaScript 變量可以存儲任何類型的值。例如,在 JavaScript 中,將一個數(shù)字賦給變量,然后將一個字符串賦給同一個變量是有效的:
let i = 10; i = "ten";
2. 使用 var 進(jìn)行變量聲明。
在 ES6 之前的 JavaScript 中,聲明變量的唯一方式是使用 var
關(guān)鍵字,無法聲明常量。var
的語法與 let
類似:
var x; var data = [], count = data.length; for (var i = 0; i < count; i++) console.log(data[i]);
雖然 var
和 let
具有相同的語法,但它們之間有重要的區(qū)別:
· 使用 var
聲明的變量沒有塊級作用域。這些變量的作用域限制在包含函數(shù)的函數(shù)體內(nèi),無論它們在函數(shù)內(nèi)部的嵌套有多深。
· 如果在函數(shù)體外部使用 var
,它將聲明一個全局變量。然而,使用 var
聲明的全局變量和使用 let
聲明的全局變量之間存在重要區(qū)別。使用 var
聲明的全局變量被實(shí)現(xiàn)為全局對象的屬性??梢允褂?nbsp;globalThis
引用全局對象。因此,如果在函數(shù)外部編寫 var x = 2;
,它等同于編寫 globalThis.x = 2;
。然而,需要注意的是,這個類比并不完全準(zhǔn)確,因?yàn)橥ㄟ^全局 var
創(chuàng)建的屬性無法使用 delete
運(yùn)算符刪除。使用 let
和 const
聲明的全局變量和常量不是全局對象的屬性。
· 與使用 let
聲明的變量不同,使用 var
可以多次聲明具有相同名稱的變量。由于 var
變量具有函數(shù)作用域而不是塊級作用域,這種重新聲明非常常見。變量 i
經(jīng)常用于存儲整數(shù)值,特別是作為 for
循環(huán)中的索引變量。在包含多個 for
循環(huán)的函數(shù)中,每個循環(huán)通常以 for (var i = 0; ...)
開始。由于 var
不限制這些變量的作用域僅限于循環(huán)體,每次迭代(無害地)重新聲明和重新初始化同一個變量。
· var
最顯著的特點(diǎn)之一是變量提升。使用 var
時,聲明被提升到包含函數(shù)的頂部。然而,變量的初始化仍然發(fā)生在代碼中的原始位置;只是變量的定義被移動到函數(shù)的頂部。因此,使用 var
聲明的變量可以在包含函數(shù)的任何位置使用,而不會生成錯誤。如果尚未執(zhí)行初始化代碼,變量的值可能是 undefined
,但是在初始化之前仍然可以使用變量,而不會引發(fā)錯誤(這可能是錯誤的來源之一,也是 let
解決的最重要的錯誤傾向特性之一。如果使用 let
聲明變量并嘗試在 let
語句運(yùn)行之前使用它,您將得到錯誤而不是 undefined
值)。
使用未聲明的變量。
在嚴(yán)格模式下,嘗試使用未聲明的變量會在運(yùn)行時觸發(fā)引用錯誤。然而,在嚴(yán)格模式之外,如果將值賦給未經(jīng) let
、const
或 var
聲明的名稱,將創(chuàng)建一個新的全局變量。此外,不管賦值語句在函數(shù)或代碼塊內(nèi)嵌套多深,它都會創(chuàng)建一個全局變量。這種行為當(dāng)然是不可取的,因?yàn)樗赡軐?dǎo)致缺陷,是使用嚴(yán)格模式的一個強(qiáng)有力的理由。以這種意外方式創(chuàng)建的全局變量的行為類似于使用 var
聲明的全局變量,因?yàn)樗鼈兌x了全局對象的屬性。但是,與通過適當(dāng)?shù)?nbsp;var
聲明定義的屬性不同,這些屬性可以使用 delete
操作刪除。
3. 解構(gòu)賦值。
ES6 引入了一種復(fù)合聲明和賦值語法,稱為 "解構(gòu)賦值"。在解構(gòu)賦值中,等號右側(cè)的值是一個數(shù)組或?qū)ο螅ㄒ粋€ "結(jié)構(gòu)化" 值),而左側(cè)模擬了數(shù)組或?qū)ο笞置嬲Z法以指定一個或多個變量。當(dāng)發(fā)生解構(gòu)賦值時,一個或多個值從右側(cè)的值中提?。?quot;解構(gòu)")并保存到左側(cè)列出的變量中。解構(gòu)賦值通常用于初始化 const
、let
或 var
聲明中的變量,但也可以用于常規(guī)賦值表達(dá)式(用于將值賦給先前聲明的變量)。此外,在定義函數(shù)參數(shù)時也可以使用解構(gòu)賦值。
以下是演示數(shù)組值解構(gòu)的代碼片段:
// 等同于 let x = 1, y = 2 let [x, y] = [1, 2]; // 等同于 x = x + 1, y = y + 1 [x, y] = [x + 1, y + 1]; // 交換兩個變量的值 [x, y] = [y, x]; // => [3, 2]:增加和交換后的值 [x, y]
解構(gòu)賦值極大地簡化了返回數(shù)組的函數(shù)的使用:
// 將 [x, y] 坐標(biāo)轉(zhuǎn)換為 [r, theta] 極坐標(biāo) function toPolar(x, y) { return [Math.sqrt(x * x + y * y), Math.atan2(y, x)]; } // 將極坐標(biāo)轉(zhuǎn)換回直角坐標(biāo) function toCartesian(r, theta) { return [r * Math.cos(theta), r * Math.sin(theta)]; } // r == Math.sqrt(2); theta == Math.PI/4 let [r, theta] = toPolar(1.0, 1.0); // [x, y] == [1.0, 1.0] let [x, y] = toCartesian(r, theta);
如前所述,變量和常量可以在各種 JavaScript for
循環(huán)中聲明和使用。在這個情境下,變量解構(gòu)也同樣適用。下面的代碼遍歷對象的所有屬性名稱/值對,并使用解構(gòu)賦值將一個兩元素數(shù)組轉(zhuǎn)換為單個變量:
// 要遍歷的對象 let o = { x: 1, y: 2 }; for (const [name, value] of Object.entries(o)) { // 打印 "x 1" 和 "y 2" console.log(name, value); }
在解構(gòu)賦值中,左側(cè)的變量數(shù)目不必與右側(cè)數(shù)組的元素數(shù)目完全匹配。左側(cè)多余的變量將被賦值為 undefined
,而右側(cè)多余的值將被忽略。左側(cè)的變量列表可以包含額外的逗號,以跳過右側(cè)的某些值:
// x == 1; y == undefined let [x, y] = [1]; // x == 1; y == 2 [x, y] = [1, 2, 3]; // x == 2; y == 4 [, x, , y] = [1, 2, 3, 4];
使用解構(gòu)賦值時,如果要將所有未使用或剩余的值收集到一個變量中,可以在左側(cè)的最后一個變量名前放置三個點(diǎn)(...
):
// y == [2, 3, 4] let [x, ...y] = [1, 2, 3, 4];
解構(gòu)賦值也可以用于嵌套數(shù)組。在這種情況下,賦值的左側(cè)應(yīng)該類似于嵌套的數(shù)組字面值:
// a == 1; b == 2; c == 2.5 let [a, [b, c]] = [1, [2, 2.5], 3];
數(shù)組解構(gòu)的一個令人印象深刻的特性是,它不僅限于數(shù)組!實(shí)際上,賦值的右側(cè)可以是任何可迭代對象,包括可以在 for/of
循環(huán)中使用的對象:
// first == "H"; rest == ["e", "l", "l", "o"] let [first, ...rest] = "Hello";
解構(gòu)賦值也適用于右側(cè)為對象值的情況。在這種情況下,左側(cè)類似于一個對象字面值,其中包含用花括號括起的用逗號分隔的變量名列表:
// 一個 RGBA 顏色對象 let transparent = { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }; // r == 0.0; g == 0.0; b == 0.0 let { r, g, b } = transparent;
下面的示例演示了將 Math
對象的全局函數(shù)復(fù)制到變量中,以便更輕松地處理復(fù)雜的三角計算:
// 等同于 const sin = Math.sin, cos = Math.cos, tan = Math.tan; const { sin, cos, tan } = Math;
請記住,上述代碼中 Math
對象的屬性遠(yuǎn)遠(yuǎn)不止三個被解構(gòu)的變量。沒有按名稱提及的屬性將被忽略。如果解構(gòu)賦值的左側(cè)包含一個不是 Math
屬性的變量名,那么該變量將被賦值為 undefined
。
在上述對象解構(gòu)的每個示例中,我們選擇了與被解構(gòu)對象的屬性匹配的變量名。這保持了簡單和易于理解的語法,但并不是嚴(yán)格必需的。對象解構(gòu)賦值的左側(cè)的每個標(biāo)識符都可以是一個由冒號分隔的對,其中第一個標(biāo)識符是要解構(gòu)的屬性名稱,第二個標(biāo)識符是要將值賦給的變量:
// 等同于 const cosine = Math.cos, tangent = Math.tan; const { cos: cosine, tan: tangent } = Math;
需要注意的是,變量名與屬性名不同時,對象解構(gòu)的語法變得過于復(fù)雜,從而使其變得不太實(shí)用。在這種情況下,我通常避免使用縮寫形式。如果選擇使用它,請記住屬性名始終必須在冒號的左側(cè),無論是在對象字面值中還是在對象解構(gòu)賦值中。
使用嵌套對象、對象內(nèi)的數(shù)組或?qū)ο髢?nèi)的數(shù)組可以使解構(gòu)賦值變得更加復(fù)雜,但它仍然是有效的:
// 包含兩個坐標(biāo)點(diǎn)對象的數(shù)組 let points = [{ x: 1, y: 2 }, { x: 3, y: 4 }]; // 解構(gòu)為 4 個變量 let [{ x: x1, y: y1 }, { x: x2, y: y2 }] = points; // => true (x1 === 1 && y1 === 2 && x2 === 3 && y2 === 4)
如果解構(gòu)的不是對象數(shù)組,還可以解構(gòu)對象中的數(shù)組:
// 包含兩個數(shù)組屬性的對象 let points = { p1: [1, 2], p2: [3, 4] }; // 解構(gòu)為 4 個變量 let { p1: [x1, y1], p2: [x2, y2] } = points; // => true (x1 === 1 && y1 === 2 && x2 === 3 && y2 === 4)
類似這樣的復(fù)雜解構(gòu)語法可能難以編寫和理解,通常會使傳統(tǒng)的代碼(如 let x1 = points.p1[0];
)更加直觀和易懂。
到此這篇關(guān)于JavaScript 中的變量聲明與賦值的文章就介紹到這了,更多相關(guān)js變量聲明和賦值內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)Tab選項(xiàng)卡切換
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)Tab選項(xiàng)卡切換效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-02-02JavaScript實(shí)現(xiàn)獲得所有兄弟節(jié)點(diǎn)的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)獲得所有兄弟節(jié)點(diǎn)的方法,實(shí)例分析了javascript節(jié)點(diǎn)遍歷的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07詳細(xì)談?wù)凟S6中的symbol數(shù)據(jù)類型
這篇文章主要給大家介紹了關(guān)于ES6中symbol數(shù)據(jù)類型的相關(guān)資料,Symbol函數(shù)的特性是每一個Symbol函數(shù)的返回值都是唯一的,可以通過給symbol函數(shù)傳遞不同的參數(shù)產(chǎn)生具有不同標(biāo)記的值,需要的朋友可以參考下2021-08-08IE中直接運(yùn)行顯示當(dāng)前網(wǎng)頁中的圖片 推薦
IE中直接運(yùn)行顯示當(dāng)前網(wǎng)頁中的圖片 推薦...2006-08-08uni-app開發(fā)微信小程序之H5壓縮上傳圖片的問題詳解
這次項(xiàng)目中做了一個圖片上傳,要求是大于2MB的就壓縮成2MB一下的再上傳,下面這篇文章主要給大家介紹了關(guān)于uni-app開發(fā)微信小程序之H5壓縮上傳圖片的問題,需要的朋友可以參考下2023-03-03