浅析TypeScript中const和readonly的区别、枚举和常量枚举的区别以及关于typescript中枚举的相关知识
<h3><span style="font-size: 16px">一、const 和 readonly 的区别</span></h3><p><span style="font-size: 16px">1、TypeScript 中不可变量的实现方法有两种:</span></p>
<ul class="list-paddingleft-2">
<li><span style="font-size: 16px">使用 ES6 的 const 关键字声明的值类型</span></li>
<li><span style="font-size: 16px">被 readonly 修饰的属性</span></li>
</ul>
<p><span style="font-size: 16px">2、TypeScript 中 readonly:</span></p>
<p><span style="font-size: 16px"> TypeScript 中的只读修饰符,可以声明更加严谨的可读属性。通常在 <code>interface</code> 、 <code>Class</code> 、 <code>type</code> 以及 <code>array</code> 和 <code>tuple</code> 类型中使用它,也可以用来定义一个函数的参数。</span></p>
<p><span style="font-size: 16px">3、两者区别:</span></p>
<p><span style="font-size: 16px">(1)<code>const</code> 用于变量, <code>readonly</code> 用于属性</span></p>
<p><span style="font-size: 16px">(2)<code>const</code> 在运行时检查, <code>readonly</code> 在编译时检查</span></p>
<p><span style="font-size: 16px">(3)<code>const</code> 声明的变量不得改变值,这意味着,<code>const</code> 一旦声明变量,就必须立即初始化,不能留到以后赋值;</span></p>
<p><span style="font-size: 16px"> <code>readonly</code> 修饰的属性能确保自身不能修改属性,但是当你把这个属性交给其它并没有这种保证的使用者(允许出于类型兼容性的原因),他们能改变</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">const</span><span style="color: rgba(0, 0, 0, 1)"> foo: {
</span><span style="color: rgba(0, 0, 255, 1)">readonly</span><span style="color: rgba(0, 0, 0, 1)"> bar: number;
} </span>=<span style="color: rgba(0, 0, 0, 1)"> {
bar: </span><span style="color: rgba(128, 0, 128, 1)">123</span><span style="color: rgba(0, 0, 0, 1)">
};
function iMutateFoo(foo: { bar: number }) {
foo.bar </span>= <span style="color: rgba(128, 0, 128, 1)">456</span><span style="color: rgba(0, 0, 0, 1)">;
}
iMutateFoo(foo);
console.log(foo.bar); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 456</span></span></pre>
</div>
<p><span style="font-size: 16px">(4)<strong><code>const</code> 保证的不是变量的值不得改动,而是变量指向的那个内存地址不得改动</strong>,例如使用 <code>const</code> 变量保存的数组,可以使用 <code>push</code> , <code>pop</code> 等方法。</span></p>
<p><span style="font-size: 16px"> 但是<strong>如果使用 <code>ReadonlyArray<number></code> 声明的数组不能使用 <code>push</code> , <code>pop</code> 等方法</strong>。</span></p>
<h3><span style="font-size: 16px">二、枚举和常量枚举的区别</span></h3>
<p><span style="font-size: 16px">1、枚举和常量枚举(const枚举):使用枚举可以清晰地表达意图或创建一组有区别的用例</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 枚举</span>
<span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> Color { Red, Green, Blue }
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 常量枚举</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> Color { Red, Green, Blue }</span></span></pre>
</div>
<p><span style="font-size: 16px">2、区别:</span></p>
<p><span style="font-size: 16px">(1)枚举会被编译时会编译成一个对象,可以被当作对象使用</span></p>
<p><span style="font-size: 16px">(2)<strong><code>const</code> 枚举会在 typescript 编译期间被删除,<code>const</code> 枚举成员在使用的地方会被内联进来,避免额外的性能开销</strong></span></p>
<p><span style="font-size: 16px"> 我们先看下面代码,枚举会被编译成什么:</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 枚举</span>
<span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> Color {
Red,
Green,
Blue
}
</span><span style="color: rgba(0, 0, 255, 1)">var</span> sisterAn =<span style="color: rgba(0, 0, 0, 1)"> Color.Red
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 会被编译成 JavaScript 中的 var sisterAn = Color.Red
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 即在运行执行时,它将会查找变量 Color 和 Color.Red</span></span></pre>
</div>
<p><span style="font-size: 16px"> 我们再看下 常量枚举 会被编译成什么:</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 常量枚举</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> Color {
Red,
Green,
Blue
}
</span><span style="color: rgba(0, 0, 255, 1)">var</span> sisterAn =<span style="color: rgba(0, 0, 0, 1)"> Color.Red
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 会被编译成 JavaScript 中的 var sisterAn = 0
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在运行时已经没有 Color 变量</span></span></pre>
</div>
<p><span style="font-size: 16px"> 由此可见,使用 常量枚举 会有更好的性能。</span></p>
<p><span style="font-size: 16px"> 定义的枚举,在经过编译器编译后是一个对象,这个对象我们可以在程序运行时使用,前面有说到。但有时定义枚举可能只是为了让程序可读性更好,而不需要编译后的代码,即不需要编译成对象。typescript中考虑到这种情况,所以加入了 const enum (完全嵌入的枚举)。</span></p>
<h3><span style="font-size: 16px">三、关于 typescript 中的枚举介绍</span></h3>
<p><span style="font-size: 16px">1、数字枚举:即枚举里所有属性的值都是数字类型</span></p>
<p><span style="font-size: 16px"> 当枚举里的属性没指定具体值时,默认值是从 0 开始依次排列,你也可以自己指定具体值,剩下的也是依次递增:</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> Colors {
Red,
Blue </span>= <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">,
Yellow
}
console.log(Colors.Red) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 0</span>
console.log(Colors.Blue) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 5</span>
console.log(Colors.Yellow) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 6</span></span></pre>
</div>
<p><span style="font-size: 16px"> 数字枚举在定义值的时候,可以是 常量 或者是 计算出来的。</span></p>
<p><span style="font-size: 16px">(1)它是枚举的第一个成员且没有初始化,这种情况下它被赋予值0 (如上)<code></code></span></p>
<p><span style="font-size: 16px">(2)它未初始化器且它之前的枚举成员是一个 <em>数字</em>常量。 这种情况下,当前枚举成员的值为它上一个枚举成员的值加1(如上)</span></p>
<p><span style="font-size: 16px">(3)枚举成员使用 <em>常量枚举表达式</em>初始化</span></p>
<p><span style="font-size: 16px"> A的值是被计算出来的。注意注释部分,如果某个属性的值是计算出来的,那么它后面一位的成员必须要初始化值</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">const</span> getValue = () =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
}
</span><span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> List {
A </span>=<span style="color: rgba(0, 0, 0, 1)"> getValue(),
B </span>= <span style="color: rgba(128, 0, 128, 1)">2</span>,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 此处必须要初始化值,不然编译不通过</span>
<span style="color: rgba(0, 0, 0, 1)">C
}
console.log(List.A) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 0</span>
console.log(List.B) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2</span>
console.log(List.C) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3</span></span></pre>
</div>
<p><span style="font-size: 16px">2、反向映射</span></p>
<p><span style="font-size: 16px"> 可以通过 Enum 或者 Enum.key 的方式获取到对应的值。typescript 还支持反向映射,即可以通过值来获取键,不过反向映射只支持数字枚举。</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> Status {
Success </span>= <span style="color: rgba(128, 0, 128, 1)">200</span><span style="color: rgba(0, 0, 0, 1)">,
NotFound </span>= <span style="color: rgba(128, 0, 128, 1)">404</span><span style="color: rgba(0, 0, 0, 1)">,
Error </span>= <span style="color: rgba(128, 0, 128, 1)">500</span><span style="color: rgba(0, 0, 0, 1)">
}
console.log(Status.Success) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 200</span>
console.log(Status[<span style="color: rgba(128, 0, 128, 1)">200</span>]) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Success</span>
console.log(Status) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Success</span></span></pre>
</div>
<p><span style="font-size: 16px">3、字符串枚举要求每个字段的值都必须是字符串字面量,或者是另外一个字符串枚举成员</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> Str {
Str1 </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">this is string one</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
Str2 </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">this is string two</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
Str3 </span>= Str1<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这里引用了Str1的值</span>
}</span></pre>
</div>
<p><span style="font-size: 16px">4、异构枚举:把数字枚举和字符串枚举混用,就形成了异构枚举,这种方式很容易引起混淆,不推荐使用。</span></p>
<p><span style="font-size: 16px">5、枚举成员:枚举成员的值不可修改。</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">Char.a = <span style="color: rgba(128, 0, 128, 1)">6</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Cannot assign to 'a' because it is a read-only property</span></span></pre>
</div>
<p><span style="font-size: 16px"> 枚举成员可以分为<strong>常量</strong>的和<strong>需要计算的</strong></span></p>
<p><span style="font-size: 16px">(1)<strong>const enum(</strong>常量枚举<strong>):</strong></span></p>
<ol>
<li><span style="font-size: 16px">没有设置初始值</span></li>
<li><span style="font-size: 16px">对已有枚举成员的引用</span></li>
<li><span style="font-size: 16px">常量的表达式</span></li>
</ol>
<p><span style="font-size: 16px"> 常量枚举成员会在编译时计算出结果,然后以常量的形式,出现在运行时环境</span></p>
<p><span style="font-size: 16px">(2)<strong>computed enum(</strong>需要计算的枚举成员<strong>)</strong></span></p>
<p><span style="font-size: 16px"> 这些枚举成员的值不会在编译阶段计算,而是保留到程序的执行阶段</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> Char {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 常量枚举成员</span>
<span style="color: rgba(0, 0, 0, 1)">a,
b </span>=<span style="color: rgba(0, 0, 0, 1)"> Char.a,
c </span>= <span style="color: rgba(128, 0, 128, 1)">1</span> + <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 非常量枚举成员</span>
d =<span style="color: rgba(0, 0, 0, 1)"> Math.random(),
e </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">.length
}
console.log(Char);</span></span></pre>
</div>
<p><span style="font-size: 16px">6、<strong>常量枚举</strong></span></p>
<p><span style="font-size: 16px"> 常量枚举其实就是是在 enum关键字前使用 const 修饰符,常量枚举会<strong>在编译阶段被移除</strong></span></p>
<p><span style="font-size: 16px"> 作用:当我们不需要一个对象,而需要对象的值,就可以使用常量枚举,这样就可以避免在编译时生成多余的代码和间接引用</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> Month {
Jan,
Feb,
Mar
}
console.log(Month);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ReferenceError: Month is not defined </span>
console.log(Month.Jan); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">输出0</span></span></pre>
</div>
<p><span style="font-size: 16px"> 常量枚举成员在使用的地方被内联进来,且常量枚举不可能有<strong>计算成员</strong></span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> Directions {
Up,
Right,
Down,
Left,
UpRight </span>= <span style="color: rgba(128, 0, 128, 1)">3</span> + <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">,
RightDown </span>= Directions.Right + <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">,
LeftDown </span>= <span style="color: rgba(128, 0, 128, 1)">9</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> RightUp = 'hello'.length<br></span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> const enum member initializers can only </span><span style="color: rgba(0, 128, 0, 1)">contain literal values and other computed enum values</span>
}</span></pre>
</div>
<p> </p><br><br>
来源:https://www.cnblogs.com/goloving/p/15412110.html
頁:
[1]