最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript實現(xiàn)枚舉的幾種方法總結(jié)

 更新時間:2023年08月30日 08:23:40   作者:liangyue  
在前端開發(fā)中,我們可能經(jīng)常需要用到枚舉,使用枚舉的好處是為了讓代碼的可讀性更強(qiáng),避免直接使用數(shù)字或未知的字符串,但是在JavaScript中,要自己實現(xiàn)一個枚舉功能,那么大家能想到多少種實現(xiàn)枚舉的方法呢,我將介紹幾種實現(xiàn)枚舉的好方法

基于普通對象

我們來考慮一個場景:T恤的尺寸:Small、Medium、Large三種類型,那么我們使用普通對象的方式來實現(xiàn),代碼如下:

const Sizes = {
  Small: 'small',
  Medium: 'medium',
  Large: 'large',
}

基于這種方式實現(xiàn)一個枚舉是非常簡單的,而且也足夠的清晰,此時Sizes就是一個基于JavaScript普通對象的枚舉,它有3個命名常量:Size.Small、Size.MediumSize.Large,我們可以通過Size.small來獲取對應(yīng)的枚舉值。

優(yōu)點

  • 簡單:使用這種方式實現(xiàn)枚舉是非常簡單,只需要定義一個帶有鍵和值的對象即可

缺點

  • 容易被外部修改

當(dāng)我們在維護(hù)一個大型的代碼倉庫時,枚舉值可能會被意外更改,代碼如下:

const size1 = Sizes.Medium
const size2 = Sizes.Medium = 'foo' // Changed!
console.log(size1 === Sizes.Medium) // logs false

如代碼中所示,當(dāng)枚舉被修改后,之后的邏輯將會出現(xiàn)問題,這也就是說,我們實現(xiàn)枚舉的時候需要考慮對象的值不能被修改。

基于Symbol

我們也可以這樣實現(xiàn)一個枚舉:

const Sizes = {
  Small: Symbol('small'),
  Medium: Symbol('medium'),
  Large: Symbol('large'),
}
const mySize = Sizes.Large;
console.log(mySize === Sizes.Large); // true
console.log(mySize === Symbol('large')); // false

使用這種方式實現(xiàn)的枚舉看上去和機(jī)遇普通對象的方式類似,只是把對象中的值修改成了Symbol類型,那么這樣和剛才的方式又有什么不同呢?

優(yōu)點

  • 必須使用枚舉本身來進(jìn)行比較:也就是上面代碼中我們必須使用Sizes.Large來比較,再重新創(chuàng)建一個Symbol('large')對比的話則不相等,而對比第一種方法,只要字符串相同即為相同,這種對比方式更加嚴(yán)格了

缺點

  • 不能使用JSON.stringify,使用JSON.stringify會將Symbol轉(zhuǎn)為undefined、null或直接跳過,代碼如下:
console.log(JSON.stringify(Sizes.Small)); // undefined
console.log(JSON.stringify([Sizes.Small])); // [null]
console.log(JSON.stringify({ size: Sizes.Small })) // {}
  • 容易被外部修改,這點與第一種方案的情況類似,接下來,我們將介紹如何能夠保證枚舉值不會被修改的方案

基于Object.freeze

使用Object.freeze可以使一個對象被凍結(jié):被凍結(jié)的對象不能再被更改:不能添加新的屬性,不能移除現(xiàn)有的屬性,不能更改它們的可枚舉性、可配置性、可寫性或值,對象的原型也不能被重新指定。我們使用這種實現(xiàn)枚舉,代碼如下:

const Sizes = Object.freeze({
  Small: 'small',
  Medium: 'medium',
  Large: 'large',
})
const mySize = Sizes.Large;
Sizes.Large = '111'
console.log(mySize === Sizes.Large) // true

使用這種方式,就算去修改枚舉值也是無效的,如果在嚴(yán)格模式下,這種賦值的情況還會拋出錯誤。

優(yōu)點

  • 有效防止枚舉值被修改

缺點

  • 當(dāng)拼寫錯誤時,會直接返回undefined ,比如我們直接獲取Sizes.a,此時會返回undefined,這個問題在前面的幾個方案中也是同樣的,我們在開發(fā)過程中,應(yīng)該是更希望拋出一個錯誤,這樣在開發(fā)階段更直接的發(fā)現(xiàn)問題所在。于是,就有了下面一種方案。

基于Proxy

使用Proxy用于創(chuàng)建一個對象的代理,從而實現(xiàn)基本操作的攔截和自定義,Proxy并不會改變原始對象的結(jié)構(gòu),而且我們可以實現(xiàn)如下兩個需求:

  • 訪問不存在枚舉時,拋出錯誤
  • 修改枚舉對象屬性時,拋出錯誤

這樣,就可以同時滿足我們前面幾種方案遇到的問題了,接下來,我們封裝一個函數(shù),代碼如下:

function Enum(baseEnum) {
  return new Proxy(baseEnum, {
    get(target, name) {
      if (!baseEnum.hasOwnProperty(name)) {
        throw new Error(`"${name}" value does not exist in the enum`)
      }
      return baseEnum[name]
    },
    set(target, name, value) {
      throw new Error('Cannot add a new value to the enum')
    }
  })
}

這個函數(shù)中,我們傳入一個初始枚舉對象,當(dāng)我們訪問某個屬性的時候,如果沒有將會拋出錯誤"${name}" value does not exist in the enum,當(dāng)我們修改值的時候,也會拋出一個錯誤Cannot add a new value to the enum接下來,我們使用這個函數(shù)包裝一下Sizes,代碼如下:

const Sizes = Enum({
  Small: 'small',
  Medium: 'medium',
  Large: 'large',
})
const mySize = Sizes.Large; // large
Sizes.Small = '1' // 拋出錯誤: Cannot add a new value to the enum
console.log(Sizes.a) // 拋出錯誤:"a" value does not exist in the enum

優(yōu)點

  • 枚舉值防止修改
  • 訪問不存在的枚舉時會拋出錯誤

缺點

  • 相對復(fù)雜,必須導(dǎo)入Enum函數(shù)

基于Class

另一個方法是基于JavaScript中的Class類實現(xiàn)的,這個類中包含一組靜態(tài)的字段,而每一個對應(yīng)的值本身又是這個實例,代碼如下:

class Sizes {
  static Small = new Sizes('small')
  static Medium = new Sizes('medium')
  static Large = new Sizes('large')
  #value
  constructor(value) {
    this.#value = value
  }
  toString() {
    return this.#value;
  }
}

每一個枚舉值都是一個Sizes實例,內(nèi)部有個私有屬性#value, 用來表示枚舉的原始值。我們舉幾個例子來看下使用這種方式實現(xiàn)的具有哪些特性:

const mySize = Sizes.Large;
console.log('mySize', Sizes.Large); // Sizes {}
console.log(mySize === Sizes.Large); // true
console.log(mySize === new Sizes('large')) // false
console.log('mySize string', Sizes.toString()) // large
console.log(mySize instanceof Sizes) // true

優(yōu)點

  • 可以通過instanceof來判斷是否是枚舉:上面例子中我們可以判斷出來mySize是一個枚舉
  • 這種方式枚舉的對比是基于實例的:上面例子中mySize === new Sizes('large') ,即使是相同的#value,也是不同的實例

缺點

  • 枚舉值可能會被意外修改
  • 訪問不存在的枚舉時不會拋出錯誤

總結(jié)

上面我們介紹了幾種在JavaScript中實現(xiàn)枚舉的方式,每種方式都有各自的優(yōu)缺點,相比之下,我認(rèn)為:

  • Proxy方式更為靈活,可以按照自己的需求進(jìn)行更多的定制化;
  • 如果枚舉值用的較多,且項目較大,選擇Object.freeze方式,防止枚舉值被意外修改;
  • 如果您遇到的情況相對簡單,使用基于普通對象的方式;

總之,我們最終的實現(xiàn)要盡量的簡單,不要過度設(shè)計,按照具體情況選擇合適的方式。

相關(guān)文章

  • JS判斷是否為JSON對象及是否存在某字段的方法(推薦)

    JS判斷是否為JSON對象及是否存在某字段的方法(推薦)

    下面小編就為大家?guī)硪黄狫S判斷是否為JSON對象及是否存在某字段的方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • 簡單實現(xiàn)js點擊展開二級菜單功能

    簡單實現(xiàn)js點擊展開二級菜單功能

    這篇文章主要教大家簡單實現(xiàn)js點擊展開二級菜單功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • 微信小程序?qū)崿F(xiàn)圖片滾動效果示例

    微信小程序?qū)崿F(xiàn)圖片滾動效果示例

    這篇文章主要介紹了微信小程序?qū)崿F(xiàn)圖片滾動效果,結(jié)合實例形式分析了微信小程序基于swiper組件的圖片滾動效果相關(guān)實現(xiàn)技巧與操作注意事項,需要的朋友可以參考下
    2018-12-12
  • javascript動態(tài)的改變IFrame的高度實現(xiàn)自動伸展

    javascript動態(tài)的改變IFrame的高度實現(xiàn)自動伸展

    動態(tài)的改變IFrame的高度,實現(xiàn)IFrame自動伸展,父頁面也自動神縮,實現(xiàn)原理很簡單就是在IFrame子頁面一加載的時候,調(diào)用父IFrame對象,改變其高度,感興趣的朋友可以了解下
    2013-10-10
  • 微信小程序?qū)崿F(xiàn)左滑刪除效果

    微信小程序?qū)崿F(xiàn)左滑刪除效果

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)左滑刪除效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • JavaScript實現(xiàn)與web通信的方法詳解

    JavaScript實現(xiàn)與web通信的方法詳解

    這篇文章主要介紹了JavaScript實現(xiàn)與web通信的方法詳解,文章通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • JS+Ajax+Jquery實現(xiàn)頁面無刷新分頁以及分組 超強(qiáng)的實現(xiàn)

    JS+Ajax+Jquery實現(xiàn)頁面無刷新分頁以及分組 超強(qiáng)的實現(xiàn)

    JS+Ajax+Jquery實現(xiàn)頁面無刷新分頁以及分組 超強(qiáng)的實現(xiàn) 加上你的CSS完全可以與EXT媲美哦
    2009-08-08
  • js實現(xiàn)簡單排列組合的方法

    js實現(xiàn)簡單排列組合的方法

    這篇文章主要介紹了js實現(xiàn)簡單排列組合的方法,可實現(xiàn)數(shù)學(xué)上排列組合算法功能,涉及JavaScript數(shù)組與字符串操作技巧,需要的朋友可以參考下
    2016-01-01
  • 使用babylon.js導(dǎo)入導(dǎo)出模型

    使用babylon.js導(dǎo)入導(dǎo)出模型

    Babylon.js是一個開源的3D圖形引擎,支持導(dǎo)入和渲染多種3D模型格式,如.obj、.gltf、.fbx等,通過使用SceneLoader或特定格式的加載器(如GLTFLoader或FBXLoader),可以輕松導(dǎo)入模型,雖然Babylon.js不直接支持導(dǎo)出模型
    2024-11-11
  • bootstrap datepicker限定可選時間范圍實現(xiàn)方法

    bootstrap datepicker限定可選時間范圍實現(xiàn)方法

    這篇文章主要介紹了bootstrap datepicker限定可選時間范圍的實現(xiàn)方法,本文涉及到相關(guān)知識點,通過實例給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2016-09-09

最新評論

丰台区| 巴楚县| 桑日县| 凤翔县| 屯门区| 张掖市| 错那县| 罗甸县| 崇阳县| 宾阳县| 济源市| 丁青县| 漯河市| 福海县| 余庆县| 沙洋县| 双辽市| 镇巴县| 吉安县| 黄骅市| 龙泉市| 恭城| 台东县| 潮安县| 博野县| 张家港市| 二连浩特市| 富裕县| 蕲春县| 宽甸| 阿拉善右旗| 宁波市| 惠州市| 常德市| 桐庐县| 彩票| 定兴县| 稻城县| 双柏县| 云南省| 通山县|