JavaScript中定義列舉的語法是什麼?
列舉或列舉型別是特殊的資料型別,它將變數設定為一組預定義的常量。在其他語言中,提供列舉資料型別以用於此應用程式。Javascript 本身不直接具有列舉型別,但我們可以透過 javascript 實現類似於列舉的型別。在本文中,我們將介紹在 javascript 中定義列舉型別的語法和用法。
以下語法顯示了在 javascript 中列舉的基本實現,我們可以定義一個物件來封裝列舉型別,併為每個列舉值分配鍵。
語法
const EnumType = { <enumConstant1> : <value1>, <enumConstant2> : <value2>, ... <enumConstantN> : <valueN> }
讓我們來看一個例子,我們在這個例子中在 javascript 程式碼中使用帶有整數值的列舉型別。
示例
<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { const Direction = { E: 1, W: 2, N: 3, S: 4, NE: 31, NW: 32, SE: 41, SW: 42, } let myDirection = 41 if (myDirection === Direction.SE) { content += "Yes, your direction is South-East" + '<br>' } } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>
此方法適用於小型程式碼庫,但在某些情況下可能會產生一些歧義。例如,在下面的示例中,開發人員可能會將方向寫成小寫形式的第一個字母,但是字串匹配失敗並返回 false。
示例
<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { const Direction = { E: 'East', W: 'West', N: 'North', S: 'South', NE: 'North-East', NW: 'North-West', SE: 'South-East', SW: 'South-West', } let myDirection = 'south-East' if (myDirection === Direction.SE) { content += "Yes, your direction is South-East" + '<br>' } else { content += "No, your direction is not South-East" + '<br>' } } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>
開發人員還可以建立意外匹配的不相關列舉,因為它們只是兩種原始型別的值,所以它們會被條件運算子匹配。讓我們透過一個例子來看一下這個問題:
示例
<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { const Direction = { E: 1, W: 2, N: 3, S: 4, NE: 31, NW: 32, SE: 41, SW: 42, } const Vehicle = { Bus: 1, Car: 2, Motorcycle: 3, Truck: 4 } if (Direction.S === Vehicle.Truck) { content += "Yes, your vehicle type is truck" + '<br>' } } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>
在這個例子中,建立了兩種不同的列舉型別,但在 if 塊中檢查它們的值時,它們卻混淆了。這是不可取的。另一件事是使用整數或數字在語義上是不正確的。例如,方向不是整數或字串,它們必須有自己的型別才能更好地表示。
使用 Symbol 型別的列舉
在 Javascript 中,有一個名為 Symbol() 的概念。符號不會相互衝突。因此,如果我們使用 Symbol 來定義值,它將更合適且更不容易出錯。語法如下所示。
語法
const EnumType = { const EnumType = { <enumConstant1> : Symbol(<value1>), <enumConstant2> : Symbol(<value2>), ... <enumConstantN> : Symbol(<valueN>) }
讓我們來看一個類似的例子,其中使用了 Symbol,讓我們檢查它們是否會衝突。
示例
<html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { const Direction = { E: Symbol(1), W: Symbol(2), N: Symbol(3), S: Symbol(4), NE: Symbol(31), NW: Symbol(32), SE: Symbol(41), SW: Symbol(42), } const Vehicle = { Bus: Symbol(1), Car: Symbol(2), Motorcycle: Symbol(3), Truck: Symbol(4), } if (Direction.S === Vehicle.Truck) { content += "Yes, your vehicle type is truck" + '<br>' } else { content += "Checking two dissimilar types." + '<br>' } } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>
建立不可變的列舉型別
到目前為止,我們已經看到了幾種列舉的實現。但是,還有一些問題。在最後一種策略中,我們也可以透過為列舉型別賦值一個新值來更新它的值。為了限制列舉更新,我們可以透過將物件傳遞到 Object.freeze() 方法中來使其不可變。讓我們透過一個例子來看一下。
語法
const EnumType = Object.freeze({ <enumConstant1> : Symbol(<value1>), <enumConstant2> : Symbol(<value2>), ... <enumConstantN> : Symbol(<valueN>) })
示例
<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { const Direction = { E: Symbol(1), W: Symbol(2), N: Symbol(3), S: Symbol(4), NE: Symbol(31), NW: Symbol(32), SE: Symbol(41), SW: Symbol(42), } content += "Value of SW: " + JSON.stringify(Direction.SE.toString()) + '<br>' Direction.SE = Symbol(50); // updating with a new value content += "Value of SW: " + JSON.stringify(Direction.SE.toString()) + '<br>' // creating an immutable object type const Vehicle = Object.freeze({ Bus: Symbol(1), Car: Symbol(2), Motorcycle: Symbol(3), Truck: Symbol(4), }) content += "Value of Car: " + JSON.stringify(Vehicle.Car.toString()) + '<br>' Vehicle.Car = Symbol(10); // updating will not affect the old value content += "Value of Car: " + JSON.stringify(Vehicle.Car.toString()) + '<br>' } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>
使用類的列舉
使用類定義列舉型別的最終方法。在類中,我們建立不同類別的靜態成員,併為同一類的不同物件賦值,這些值透過建構函式傳遞。因此,當我們從外部使用它們時,可以使用類名和成員(列舉型別)名輕鬆地使用它們。讓我們來看一個這個想法的例子。
示例
<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { class Vehicles { static Car = new Vehicles('car'); static Bus = new Vehicles('bus'); static Truck = new Vehicles('truck'); static Motorcycle = new Vehicles('motorcycle'); constructor(name) { this.name = name; } } let mot = Vehicles.Motorcycle; // mot is a vehicle of type motorcycle content += "Is mot a Vehicle enum? " + JSON.stringify(mot instanceof Vehicles) + '<br>' content += "Is 'motorcycle' string itself a Vehicle enum? " + JSON.stringify(Symbol('motorcycle') instanceof Vehicles) + '<br>' console.log('Type of mot: ', mot.constructor.name) content += 'Type of mot: ' + JSON.stringify(mot.constructor.name) + '<br>' } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>
結論
列舉或 enum 資料型別用於建立有序的常量集,這些常量可用於我們的程式以提高其可讀性。與其他語言不同,javascript 不原生支援列舉型別。有很多不同的方法可以在我們的 javascript 程式碼中設計列舉。基本列舉可以透過使用整數或字串型別值的物件生成,但是這種方法不適用於許多這樣的情況,例如,兩個具有相同型別的列舉可能會發生衝突。可能的解決方案是使用 Symbol 來避免衝突。我們還可以使我們的列舉不可變以避免不必要的更新,最合適的方法是使用類作為列舉型別。