TypeScript之枚举

枚举

枚举

‘使用枚举我们可以定义一些带名字的常量。使用枚举可以清晰地表达意图或创建一组有区别的用例。TypeScript支持数字的和基于字符串的枚举。

数字枚举

首先我们看看数字枚举,如果你使用过其它编程语言应该会很熟悉。

enum Direction {Up = 1,Down,Left,Right
}

如上,我们定义了一个数字枚举,Up使用初始化为1。其余的成员从1开始自动增长。换句话说,Direction.Up的值为 1Down2Left3Right4

我们还可以完全不适用初始化器:

enum Direction {Up,Down,Left,Right,
}

现在, Up的值为 0, Down的值为 1等等。 当我们不在乎成员的值的时候,这种自增长的行为是很有用处的,但是要注意每个枚举成员的值都是不同的。

使用枚举很简单:通过枚举的属性来访问枚举成员,和枚举的名字来访问枚举类型:

enum Respose {No = 0,Yes = 1
}
function respond (recipient: string, message: Response): void {//..
}
respond ("Princess Caroline", Response.Yes);

数字枚举可以被混入到计算过的和常量成员。简短的说,不带初始化器的枚举或者被放在第一的位置,或者被放在使用了数字常量或其它常量初始化了的枚举后面。 换句话说,下面的情况是不被允许的:

enum E {A = getSomeValue(),B, // error! 'A' is not constant-initialized, so 'B' needs an initializer
}

字符串枚举

字符串枚举的概念很简单,但是有细微的运行时的差别。在一个字符串枚举里,每个成员都必须使用字符串字面量,或者另一个字符串枚举成员进行初始化

enum Direction {Up = "Up",Down = "DOWN",Left = "LEFT",Right = "RIGHT",
}

由于字符串枚举没有自增长的行为,字符串枚举可以很好的序列化。换句话说,如果你正在调试并且必须要读一个数字枚举的运行时的值,这个值通常是很难读的 - 它并不能表达有用的信息 (尽管反相映射会有帮助),字符串枚举允许你提供一个运行时有意义的并且可读的值,独立于枚举成员的名字。

异构枚举

从技术的角度说,枚举可以混合字符串和数字成员,但是似乎你并不会这么做:

enum BooleanLikeHeterogeneousEnum {No = 0,Yes = "YES",
}

除非你真的想要利用JavaScript运行时的行为,否则我们不建议这样做。

计算的和常量成员

每个枚举成员都带有一个值,它可以是常量或计算出来的,当满足如下条件时,枚举成员被当作是常量:

  • 它是枚举的第一个成员且没有初始化器,这种情况下它被赋予值0;

    // E.X is constant:
    enum E { X }
    
  • 它不带有初始化器且它之前的枚举成员是一个数字常量。这种情况下,当前枚举成员的值为它上一个枚举成员的值加1.

    // All enum members in 'E1' and 'E2' are constant.enum E1 { X, Y, Z }enum E2 {A = 1, B, C
    }
    
  • 枚举成员使用 常量枚举表达式初始化。常量枚举表达式是TypeScript表达式的子集,它可以在编译阶段求值。当一个表达式满足下面条件之一时,它就是一个常量枚举表达式:

    • 一个枚举表达式字面量(主要是字符串字面量或数字字面量)
    • 一个对之前定义的常量枚举成员的引用 (可以是在不同的枚举类型中定义的)
    • 带括号的常量枚举表达式
    • 一元运算符 +,=,~ 其中之一应用在了常量枚举表达式
    • 常量枚举表达式做为二元运算符 +, -, *, /, %, <<, >>, >>>, &, |, ^的操作对象。 若常数枚举表达式求值后为 NaNInfinity,则会在编译阶段报错。

所有其它情况的枚举成员被当作是需要计算得出的值。

enum FileAccess {// constant membersNone,Read    		= 1 << 1,Write 			= 1 << 2,ReadWrite		= Read | Write// computed memberG = "123".length
}

联合枚举与枚举成员的类型

存在一种特殊的非计算的常量枚举成员的子集:字面量枚举成员。 字面量枚举成员是指不带有初始值的常量枚举成员,或者是值被初始化为

  • 任何字符串字面量(例如: "foo""bar""baz"
  • 任何数字字面量(例如: 1, 100
  • 应用了一元 -符号的数字字面量(例如: -1, -100

当所有枚举成员都拥有字面量枚举值时,它就带有了一种特殊的语义。

首先,枚举成员成为了类型! 例如,我们可以说某些成员 只能是枚举成员的值:

enum ShapeKind {Circle,Square,
}interface Circle {kind: ShapeKind.Circle;radius: number;
}interface Square {kind: ShapeKind.Square;sideLength: number;
}let c: Circle = {kind: ShapeKind.Square,//    ~~~~~~~~~~~~~~~~ Error!radius: 100,
}

另一个变化是枚举类型本身变成了每个枚举成员的 联合。虽然我们还没有讨论(联合类型),但你只要知道通过联合枚举,类型系统能够利用这样一个事实,它可以知道枚举里的值的集合。因此,TypeScript能够捕获在比较值的时候犯的愚蠢的错误。例如:

enum E {Foo,Bar,
}function f(x: E) {if (x !== E.Foo || x !== E.Bar) {//             ~~~~~~~~~~~// Error! Operator '!==' cannot be applied to types 'E.Foo' and 'E.Bar'.}
}

这个例子里,我们先检查 x是否不是 E.Foo。 如果通过了这个检查,然后 ||会发生短路效果, if语句体里的内容会被执行。 然而,这个检查没有通过,那么 x只能E.Foo,因此没理由再去检查它是否为 E.Bar

运行时的枚举

枚举是在运行时真正存在的对象。例如下面的枚举:

enum E {X,Y,Z
}

can actually be passed around to functions

function f(obj: { X: number }) {return obj.X;
}// Works, since 'E' has a property named 'X' which is a number.
f(E);

反向映射

除了创建一个以属性名做为对象成员的对象之外,数字枚举成员还具有了 反向映射,从枚举值到枚举名字。 例如,在下面的例子中:

enum Enum {A
}
let a = Enum.A;
let nameOfA = Enum[a]; // "A"

TypeScript可能会将这段代码编译为下面的JavaScript:

var Enum;
(function (Enum) {Enum[Enum["A"] = 0] = "A";
})(Enum || (Enum = {}));
var a = Enum.A;
var nameOfA = Enum[a]; // "A"

生成的代码中,枚举类型被编译成一个对象,它包含了正向映射( name -> value)和反向映射( value -> name)。 引用枚举成员总会生成为对属性访问并且永远也不会内联代码。

要注意的是 不会为字符串枚举成员生成反向映射。

const枚举

大多数情况下,枚举是十分有效的方案。 然而在某些情况下需求很严格。 为了避免在额外生成的代码上的开销和额外的非直接的对枚举成员的访问,我们可以使用 const枚举。 常量枚举通过在枚举上使用 const修饰符来定义。

const enum Enum {A = 1,B = A * 2
}

常量枚举只能使用常量枚举表达式,并且不同于常规的枚举,它们在编译阶段会被删除。 常量枚举成员在使用的地方会被内联进来。 之所以可以这么做是因为,常量枚举不允许包含计算成员。

const enum Directions {Up,Down,Left,Right
}let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]

生成后的代码为:

var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];

外部枚举

外部枚举用来描述已经存在的枚举类型的形状。

declare enum Enum {A = 1,B,C = 2
}

外部枚举和非外部枚举之间有一个重要的区别,在正常的枚举里,没有初始化方法的成员被当成常数成员。 对于非常数的外部枚举而言,没有初始化方法时被当做需要经过计算的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/739211.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PYTHON 120道题目详解(100-102)

100.Python中的装饰器可以用于哪些场景&#xff1f; Python中的装饰器是一个非常强大且灵活的工具&#xff0c;它们可以用于许多不同的场景。以下是一些常见的使用装饰器的场景&#xff1a; 函数增强&#xff1a;装饰器可以用来增强函数的功能&#xff0c;比如添加日志记录、性…

javaEE8(数据库编程课后习题1,2)

一&#xff1a; 二&#xff1a; 数据库内信息&#xff1a; 登录&#xff1a; 注册&#xff1a; Register.jsp <% page pageEncoding"UTF-8" import"java.sql.*"%> <!DOCTYPE html> <html lang"en"> <head> <…

未知生,焉知死!小动物S了,如何处理?一个人一生该坚持的几件事——早读(逆天打工人爬取热门微信文章解读)

天地不仁&#xff0c;以万物为刍狗 引言Python 代码第一篇 人民日报 【夜读】一个人一生该坚持的几件事第二篇 人民日报 来了&#xff01;新闻早班车要闻社会政策 结尾 “未知生&#xff0c;焉知死” 曾经视为定数的冰冷生命 在热烈的内心烛照下 应当焕发出滚烫的热情 唯有热爱…

注意力、自注意力和多头注意力的区别

本文作者&#xff1a; slience_me 注意力、自注意力和多头注意力的区别 理解注意力&#xff08;Attention&#xff09;、自注意力&#xff08;Self-Attention&#xff09;和多头注意力&#xff08;Multi-Head Attention&#xff09;之间的区别非常重要&#xff0c;因为它们是自…

[HackMyVm] Quick

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (Un…

nginx禁止国外ip访问

1.安装geoip2扩展依赖 yum install libmaxminddb-devel -y 2.下载ngx_http_geoip2_module模块 https://github.com/leev/ngx_http_geoip2_module.git 3.编译安装 ./configure --add-module/datasdb/ngx_http_geoip2_module-3.4 4.下载最新数据库文件 模块安装成功后,还要…

【阿里云系列】-基于云效构建部署NodeJS项目到ACK

准备工作 01、编写Dockerfile文件可以根据不同的环境&#xff0c;新建不同的Dockerfile文件&#xff0c;比如Dockerfile-PROD # Deliver the dist folder with NginxFROM nginx:stable-alpine ENV LANGC.UTF-8 ENV TZAsia/ShanghaiCOPY dist/ /usr/share/nginx/html COPY ngi…

speexsdp消除回声

speexsdp需要几秒的滤波时间。我测试4-7秒。 GitHub - cpuimage/WebRTC_AECM: Acoustic Echo Canceller for Mobile Module Port From WebRTC 更快的消除 webrtc_aecm 效果: 这是testecho.c样例的程序。 初始化函数&#xff1a; SpeexEchoState *speex_echo_state_init(in…

React render方法的原理?在什么时候会被触发?

一、原理 首先&#xff0c;render函数在react中有两种形式&#xff1a; 在类组件中&#xff0c;指的是render方法&#xff1a; class Foo extends React.Component {render() {return <div> Foo </div>;} } 在函数组件中&#xff0c;指的是函数组件本身&#x…

python程序结束后,浏览器程序结束后仍然保持打开状态

python中使用selenium框架&#xff0c;程序执行完后&#xff0c;让浏览器保持打开的状态 from selenium import webdriver from selenium.webdriver.chrome.options import Options # 创建Chrome选项对象 chrom_options Options() # 添加实验性选项&#xff0c;使浏览器…

uniapp开发DAPP钱包应用(一) 环境搭建 Vue+ MetaMask + ABI.json

上几节我们讲了如何通过Java后端完成链上交易、信息查询、以及如何使用web3插件实现开发自测。 这一节&#xff0c;我们来说说前端DAPP的开发实现。 1. MeteMask &#x1fa9c;Java对接&#xff08;BSC&#xff09;币安链 | BNB与BEP20的开发实践&#xff08;三&#xff09;水…

Vue3全家桶 - VueRouter - 【6】导航守卫

导航守卫 查看以下情形&#xff1a; 点击主页链接时&#xff0c;默认情况下可直接进入指定页面&#xff0c;如下图&#xff0c;但是问题是该跳转的界面是需要用户登录后方可访问的&#xff1b; 可设置导航守卫来检测用户是否登录&#xff0c;如果已登录&#xff0c;则进入后台…

华为OD机试 - 模拟数据序列化传输(Java JS Python C C++)

题目描述 模拟一套简化的序列化传输方式,请实现下面的数据编码与解码过程 编码前数据格式为 [位置,类型,值],多个数据的时候用逗号分隔,位置仅支持数字,不考虑重复等场景;类型仅支持:Integer / String / Compose(Compose的数据类型表示该存储的数据也需要编码)编码后数…

四元数(Quaternion)的一些性质

四元数(Quaternion)是用于三维旋转和定向的四部分组成的超复数&#xff0c;超复数简单理解就是比abi这样的复数更复杂的复数&#xff0c;其中abi这样的复数我们也可以叫做二元数&#xff0c;表示复平面的一点&#xff0c;对于熟悉欧拉公式的朋友就知道&#xff0c;也可以看成是…

Sui与数据平台ZettaBlock达成合作,为其公测提供数据

Sui一向以闪电般的速度、无限水平扩展著称&#xff0c;现已迅速成为DeFi活动的重要场所。近期&#xff0c;数据平台ZettaBlock宣布在其开创性的Web3数据平台发布中&#xff0c;选择Sui作为基础集成合作伙伴之一。在ZettaBlock的开放测试版发布之际&#xff0c;构建者和开发者将…

双指针算法练习

27. 移除元素 题目 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑…

Springboot @Transactional大事务处理的几点建议

1.大事务&#xff1a; 总体任务对应的事务运行时间比较长&#xff0c;长时间未提交的事务。 2.大事务的危害&#xff1a; a.并发情况下&#xff0c;数据库连接池资源占满。大事务提交不及时&#xff0c;导致连接资源释放缓慢。 b.数据库死锁和锁等待。mysql innodb存储引擎背…

JS 事件捕获、事件冒泡、事件委托

js事件机制在开发中可以说时刻使用&#xff0c;例如dom绑定事件、监听其自身事件等。js事件机制有事件捕获、事件冒泡俩种机制&#xff0c;我们分别说下这俩种机制的使用场景。 一、概念 事件捕获顺序如下&#xff1a; window > document > body > div 事件冒泡顺序…

Using WebView from more than one process

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 未经允许不得转载 目录 一、导读二、概览三、问题过程源码追踪…

【C++进阶】C++继承概念详解

C继承详解 一&#xff0c;继承的概念和定义1.1 继承的概念1.2 继承的定义1.3 继承关系和访问限定符 二&#xff0c;基类和派生类的对象赋值转移三&#xff0c;继承的作用域四&#xff0c;派生类的默认成员函数五&#xff0c;继承和友元&静态成员和继承六&#xff0c;菱形继…