只饮一瓢 發表於 2022-8-25 11:16:00

TypeScript 解构

<h1 class="postTitle">⒈解构数组</h1>
<div id="cnblogs_post_body" class="blogpost-body blogpost-body-html">
<p>  最简单的解构莫过于数组的解构赋值了:</p>
<div class="cnblogs_code">
<pre>let input = ;
let =<span style="color: rgba(0, 0, 0, 1)"> input;
console.log(first); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> outputs 1
console.log(second); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> outputs 2</span></span></span></span></span></span></pre>
</div>
<p>  这创建了2个命名变量&nbsp;<code>first</code>&nbsp;和&nbsp;<code>second</code>。 等价于下面使用了索引的代码,但更为方便:</p>
<div class="cnblogs_code">
<pre>first = input;
second = input;</span></pre>
</div>
<p>  解构作用于已声明的变量会更好:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> swap variables
= ;</span></span></pre>
</div>
<p>  作用于函数参数:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function<span style="color: rgba(0, 0, 0, 1)"> f(: ) {
    console.log(first);
    console.log(second);
}
f(input);</span></span></pre>
</div>
<p>  你可以在数组里使用<code>...</code>语法创建剩余变量:</p>
<div class="cnblogs_code">
<pre>let = ;
console.log(first); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> outputs 1
console.log(rest); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> outputs [ 2, 3, 4 ]</span></span></span></span></span></pre>
</div>
<p>  当然,由于是JavaScript, 你可以忽略你不关心的尾随元素:</p>
<div class="cnblogs_code">
<pre>let = ;
console.log(first); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> outputs 1</span></span></span></pre>
</div>
<p>  或其它元素:</p>
<div class="cnblogs_code">
<pre>let [, second, , fourth] = ;</pre>
</div>
<p>&nbsp;</p>
<p>⒉对象解构</p>
<p>  你也可以解构对象:</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
<pre>let o =<span style="color: rgba(0, 0, 0, 1)"> {
    a: "foo"<span style="color: rgba(0, 0, 0, 1)">,
    b: 12<span style="color: rgba(0, 0, 0, 1)">,
    c: "bar"<span style="color: rgba(0, 0, 0, 1)">
};
let { a, b } = o;</span></span></span></span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
</div>
<p>这通过&nbsp;<code>o.a</code>&nbsp;and&nbsp;<code>o.b</code>&nbsp;创建了&nbsp;<code>a</code>&nbsp;和&nbsp;<code>b</code>&nbsp;。 注意,如果你不需要&nbsp;<code>c</code>&nbsp;你可以忽略它。</p>
<p>就像数组解构,你可以用没有声明的赋值:</p>
<div class="cnblogs_code">
<pre>({ a, b } = { a: "baz", b: 101 });</pre>
</div>
<p>注意,我们需要用括号将它括起来,因为Javascript通常会将以&nbsp;<code>{</code>&nbsp;起始的语句解析为一个块。</p>
<p>你可以在对象里使用<code>...</code>语法创建剩余变量:</p>
<div class="cnblogs_code">
<pre>let { a, ...passthrough } =<span style="color: rgba(0, 0, 0, 1)"> o;
let total = passthrough.b + passthrough.c.length;</span></pre>
</div>
<p>⒊属性重命名</p>
<p>  你也可以给属性以不同的名字:</p>
<div class="cnblogs_code">
<pre>let { a: newName1, b: newName2 } = o;</pre>
</div>
<p>  这里的语法开始变得混乱。 你可以将&nbsp;<code>a: newName1</code>&nbsp;读做 "<code>a</code>&nbsp;作为&nbsp;<code>newName1</code>"。 方向是从左到右,好像你写成了以下样子:</p>
<div class="cnblogs_code">
<pre>let newName1 =<span style="color: rgba(0, 0, 0, 1)"> o.a;
let newName2 = o.b;</span></pre>
</div>
<p>  令人困惑的是,这里的冒号<em>不是</em>指示类型的。 如果你想指定它的类型, 仍然需要在其后写上完整的模式。</p>
<div class="cnblogs_code">
<pre>let {a, b}: {a: string, b: number} = o;</pre>
</div>
<p>⒋默认值</p>
<p>  默认值可以让你在属性为 undefined 时使用缺省值:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function keepWholeObject(wholeObject: { a: string, b?<span style="color: rgba(0, 0, 0, 1)">: number }) {
    let { a, b = 1001 } =<span style="color: rgba(0, 0, 0, 1)"> wholeObject;
}</span></span></span></pre>
</div>
<p>  现在,即使&nbsp;<code>b</code>&nbsp;为 undefined ,&nbsp;<code>keepWholeObject</code>&nbsp;函数的变量&nbsp;<code>wholeObject</code>&nbsp;的属性&nbsp;<code>a</code>&nbsp;和&nbsp;<code>b</code>&nbsp;都会有值。</p>
<p>⒌解构函数声明</p>
<p>  解构也能用于函数声明。 看以下简单的情况:</p>
<div class="cnblogs_code">
<pre>type C = { a: string, b?<span style="color: rgba(0, 0, 0, 1)">: number }
<span style="color: rgba(0, 0, 255, 1)">function f({ a, b }: C): <span style="color: rgba(0, 0, 255, 1)">void<span style="color: rgba(0, 0, 0, 1)"> {
    <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> ...
}</span></span></span></span></span></span></pre>
</div>
<p>  但是,通常情况下更多的是指定默认值,解构默认值有些棘手。 首先,你需要在默认值之前设置其格式。</p>
<p>  其次,你需要知道在解构属性上给予一个默认或可选的属性用来替换主初始化列表。 要知道&nbsp;<code>C</code>&nbsp;的定义有一个&nbsp;<code>b</code>&nbsp;可选属性:</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
<pre><span style="color: rgba(0, 0, 255, 1)">function f({ a, b = 0 } = { a: "" }): <span style="color: rgba(0, 0, 255, 1)">void<span style="color: rgba(0, 0, 0, 1)"> {
    <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> ...
<span style="color: rgba(0, 0, 0, 1)">}
f({ a: "yes" }); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> ok, default b = 0
f(); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> ok, default to {a: ""}, which then defaults b = 0
f({}); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> error, 'a' is required if you supply an argument</span></span></span></span></span></span></span></span></span></span></span></span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
</div>
<p>  要小心使用解构。 从前面的例子可以看出,就算是最简单的解构表达式也是难以理解的。 尤其当存在深层嵌套解构的时候,就算这时没有堆叠在一起的重命名,默认值和类型注解,也是令人难以理解的。 解构表达式要尽量保持小而简单。 你自己也可以直接使用解构将会生成的赋值表达式。</p>
<p>⒍展开</p>
<p>  展开操作符正与解构相反。 它允许你将一个数组展开为另一个数组,或将一个对象展开为另一个对象。 例如:</p>
<div class="cnblogs_code">
<pre>let first = ;
let second = ;
let bothPlus = ;</span></span></pre>
</div>
<p>  这会令<code>bothPlus</code>的值为<code></code>。 展开操作创建了&nbsp;<code>first</code>和<code>second</code>的一份浅拷贝。 它们不会被展开操作所改变。</p>
<p>  你还可以展开对象:</p>
<div class="cnblogs_code">
<pre>let defaults = { food: "spicy", price: "$$", ambiance: "noisy"<span style="color: rgba(0, 0, 0, 1)"> };
let search = { ...defaults, food: "rich" };</span></pre>
</div>
<p><code>  search</code>的值为<code>{ food: "rich", price: "$$", ambiance: "noisy" }</code>。 对象的展开比数组的展开要复杂的多。 像数组展开一样,它是从左至右进行处理,但结果仍为对象。 这就意味着出现在展开对象后面的属性会覆盖前面的属性。 因此,如果我们修改上面的例子,在结尾处进行展开的话:</p>
<div class="cnblogs_code">
<pre>let defaults = { food: "spicy", price: "$$", ambiance: "noisy"<span style="color: rgba(0, 0, 0, 1)"> };
let search = { food: "rich", ...defaults };</span></pre>
</div>
<p>  那么,<code>defaults</code>里的<code>food</code>属性会重写<code>food: "rich"</code>,在这里这并不是我们想要的结果。</p>
<p>  对象展开还有其它一些意想不到的限制。 首先,它仅包含对象&nbsp;自身的可枚举属性。 大体上是说当你展开一个对象实例时,你会丢失其方法:</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
<pre><span style="color: rgba(0, 0, 0, 1)">class C {
p = 12<span style="color: rgba(0, 0, 0, 1)">;
m() {
}
}
let c = <span style="color: rgba(0, 0, 255, 1)">new<span style="color: rgba(0, 0, 0, 1)"> C();
let clone =<span style="color: rgba(0, 0, 0, 1)"> { ...c };
clone.p; <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> ok
clone.m(); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)"> error!</span></span></span></span></span></span></span></span></span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
</div>
<p>  其次,TypeScript编译器不允许展开泛型函数上的类型参数。 这个特性会在TypeScript的未来版本中考虑实现。</p>
</div><br><br>
来源:https://www.cnblogs.com/coprince/p/16623655.html
頁: [1]
查看完整版本: TypeScript 解构