欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

基于普通對(duì)象

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

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

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

優(yōu)點(diǎn)

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

缺點(diǎn)

  • 容易被外部修改

當(dāng)我們?cè)诰S護(hù)一個(gè)大型的代碼倉庫時(shí),枚舉值可能會(huì)被意外更改,代碼如下:

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

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

基于Symbol

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

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

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

優(yōu)點(diǎn)

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

缺點(diǎn)

  • 不能使用JSON.stringify,使用JSON.stringify會(huì)將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 })) // {}
  • 容易被外部修改,這點(diǎn)與第一種方案的情況類似,接下來,我們將介紹如何能夠保證枚舉值不會(huì)被修改的方案

基于Object.freeze

使用Object.freeze可以使一個(gè)對(duì)象被凍結(jié):被凍結(jié)的對(duì)象不能再被更改:不能添加新的屬性,不能移除現(xiàn)有的屬性,不能更改它們的可枚舉性、可配置性、可寫性或值,對(duì)象的原型也不能被重新指定。我們使用這種實(shí)現(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)格模式下,這種賦值的情況還會(huì)拋出錯(cuò)誤。

優(yōu)點(diǎn)

  • 有效防止枚舉值被修改

缺點(diǎn)

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

基于Proxy

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

  • 訪問不存在枚舉時(shí),拋出錯(cuò)誤
  • 修改枚舉對(duì)象屬性時(shí),拋出錯(cuò)誤

這樣,就可以同時(shí)滿足我們前面幾種方案遇到的問題了,接下來,我們封裝一個(gè)函數(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')
    }
  })
}

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

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

優(yōu)點(diǎn)

  • 枚舉值防止修改
  • 訪問不存在的枚舉時(shí)會(huì)拋出錯(cuò)誤

缺點(diǎn)

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

基于Class

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

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;
  }
}

每一個(gè)枚舉值都是一個(gè)Sizes實(shí)例,內(nèi)部有個(gè)私有屬性#value, 用來表示枚舉的原始值。我們舉幾個(gè)例子來看下使用這種方式實(shí)現(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)點(diǎn)

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

缺點(diǎn)

  • 枚舉值可能會(huì)被意外修改
  • 訪問不存在的枚舉時(shí)不會(huì)拋出錯(cuò)誤

總結(jié)

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

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

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

相關(guān)文章

  • JavaScript中實(shí)現(xiàn)單體模式分享

    JavaScript中實(shí)現(xiàn)單體模式分享

    這篇文章主要介紹了JavaScript中實(shí)現(xiàn)單體模式分享,單體模式的定義:?jiǎn)误w是一個(gè)用來劃分命名空間并將一批相關(guān)方法和屬性組織在一起的對(duì)象,如果它能夠被實(shí)例化,那么只能被實(shí)例化一次,需要的朋友可以參考下
    2015-01-01
  • 自動(dòng)生成文章摘要[JavaScript 版本]

    自動(dòng)生成文章摘要[JavaScript 版本]

    這篇文章主要介紹了自動(dòng)生成文章摘要[JavaScript 版本]
    2006-12-12
  • 基于JavaScript實(shí)現(xiàn)購物網(wǎng)站商品放大鏡效果

    基于JavaScript實(shí)現(xiàn)購物網(wǎng)站商品放大鏡效果

    大家在日常生活中都有網(wǎng)購的經(jīng)驗(yàn),有的網(wǎng)站會(huì)有商品放大鏡功能,效果非常棒,那么基于js代碼是如何實(shí)現(xiàn)的呢?下面小編給大家?guī)砹嘶趈s實(shí)現(xiàn)購物網(wǎng)站商品放大鏡效果,非常不錯(cuò),感興趣的朋友參考下吧
    2016-09-09
  • JS判斷移動(dòng)端訪問設(shè)備并加載對(duì)應(yīng)CSS樣式

    JS判斷移動(dòng)端訪問設(shè)備并加載對(duì)應(yīng)CSS樣式

    JS判斷不同web訪問環(huán)境,主要針對(duì)移動(dòng)設(shè)備,提供相對(duì)應(yīng)的解析方案,本例是加載不同的css樣式
    2014-06-06
  • 淺談Javascript Base64 加密解密

    淺談Javascript Base64 加密解密

    這篇文章主要簡(jiǎn)單介紹了Javascript Base64 加密解密的使用方法,有需要的小伙伴參考下
    2014-12-12
  • 微信小程序?qū)崿F(xiàn)單個(gè)卡片左滑顯示按鈕并防止上下滑動(dòng)干擾功能

    微信小程序?qū)崿F(xiàn)單個(gè)卡片左滑顯示按鈕并防止上下滑動(dòng)干擾功能

    這篇文章主要介紹了微信小程序?qū)崿F(xiàn)單個(gè)卡片左滑顯示按鈕并防止上下滑動(dòng)干擾功能,利用小程序事件處理的api,分別讀取觸摸開始,觸摸移動(dòng)時(shí),觸摸結(jié)束的X/Y坐標(biāo),根據(jù)差值來改變整個(gè)卡片的位置,具體實(shí)例代碼跟隨小編一起看看吧
    2019-12-12
  • js跨域問題之跨域iframe自適應(yīng)大小實(shí)現(xiàn)代碼

    js跨域問題之跨域iframe自適應(yīng)大小實(shí)現(xiàn)代碼

    前幾天做公司和開心網(wǎng)合作項(xiàng)目的時(shí)候 碰到iframe 跨域自適應(yīng)的問題剛開始很迷惑 開心網(wǎng)那邊技術(shù)工程師給我發(fā)了一段這樣子的代碼。
    2010-07-07
  • 微信小程序之間的參數(shù)傳遞、獲取的操作方法

    微信小程序之間的參數(shù)傳遞、獲取的操作方法

    這篇文章主要介紹了微信小程序中如何獲取和傳遞參數(shù),包括獲取當(dāng)前頁面參數(shù)、單獨(dú)input文本框參數(shù)的獲取、表單獲取參數(shù)信息、點(diǎn)擊表格單元格信息獲取行ID以及前端頁面跳轉(zhuǎn)傳遞多個(gè)參數(shù)等,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • JavaScript工廠模式詳解

    JavaScript工廠模式詳解

    這篇文章主要介紹了JavaScript設(shè)計(jì)模式之工廠模式,結(jié)合完整實(shí)例形式分析了工廠模式的概念、原理及javascript定義與使用工廠模式的相關(guān)操作技巧,需要的朋友可以參考下
    2021-10-10
  • Jquery中刪除元素的實(shí)現(xiàn)代碼

    Jquery中刪除元素的實(shí)現(xiàn)代碼

    empty用來刪除指定元素的子元素,remove用來刪除元素,或者設(shè)定細(xì)化條件執(zhí)行刪除
    2011-12-12

最新評(píng)論