-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path16-8.html
243 lines (233 loc) · 8.04 KB
/
16-8.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="./public/favicon.ico" />
<meta http-equiv="cache-control" content="no-cache" />
<title></title>
<link rel="stylesheet" href=" https://necolas.github.io/normalize.css/8.0.1/normalize.css" />
<link rel="stylesheet" href="./hightlight/default.min.css" />
<link rel="stylesheet" href="./css/main.css" />
<link rel="stylesheet" href="./css/copybutton.css" />
<link rel="stylesheet" href="./css/hightlight.css" />
<script src="./hightlight/hightlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.11/clipboard.min.js"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-BEVZJDBC7Z"></script>
<script src="./js/gtag.js"></script>
</head>
<body>
<header>
<nav>
<h1>
<span id="toggle-menu"></span>
<a href="index.html"></a>
</h1>
</nav>
</header>
<main>
<aside>
<nav></nav>
</aside>
<article>
<h2 id="16-8">16-8 Class static initialization blocks</h2>
<p>
類別靜態初始化區塊被宣告在類別內部,區塊內部包括的代碼在初始化時會被計算。這個許可比靜態屬性更加的有彈性,像是使用
<code>try...catch</code>
或者從單一資料中設定複合欄位 。
初始化被執行當前類別宣告的上下文,藉由訪問私有狀態。這個私有狀態允許類別在相同的作用域去分享私有屬性的資訊以及其他類型或者方法
。
</p>
<pre><code class="language-js">
class ClassWithStaticInitializationBlock {
static staticProperty1 = 'Property 1';
static staticProperty2;
static {
this.staticProperty2 = 'Property 2';
}
}
console.log(ClassWithStaticInitializationBlock.staticProperty1);
// Expected output: "Property 1"
console.log(ClassWithStaticInitializationBlock.staticProperty2);
// Expected output: "Property 2"
</code></pre>
<h3>語法</h3>
<pre><code class="language-js">
class ClassWithSIB {
static {
// …
}
}
</code></pre>
<h3>說明</h3>
<p>如果沒有靜態初始化區塊,可以通過在類宣告後調用靜態方法來實現複雜的靜態初始化:</p>
<pre><code class="language-js">
class MyClass {
static init() {
// Access to private static fields is allowed here
}
}
MyClass.init();
</code></pre>
<p>
然而,這個途徑揭露了一個實作細節 (init() 方法) 給類別的使用者。
此外,凡任何初始化邏輯宣告在類別之外的不能訪問私有靜態欄位。靜態初始化區塊允許隨意的初始化邏輯在類別被執行期間被宣告。
</p>
<p>
在類別的主區塊中可以有任何數量的靜態初始化區塊。這些使用區塊和靜態交錯的欄位初始化器一起被計算,按照次序被宣告。
任何
<code>super class</code>
的靜態初始化會首先在子類之前被執行。
</p>
<p>
變數宣告在靜態區塊的作用域屬於該區塊。 包括
<code>var</code>
、
<code>function</code>
、
<code>let</code>
、
<code>const</code>
。var宣告在靜態區塊不會被提升(hoisted)。
</p>
<pre><code class="language-js">
var y = "Outer y";
class A {
static field = "Inner y";
static {
var y = this.field;
}
}
// var defined in static block is not hoisted
console.log(y); // 'Outer y'
</code></pre>
<p>
靜態塊中的
<code>this</code>
指的是該類的構造函數物件。
<code>super.property</code>
可用於訪問超類的靜態屬性。但請注意,在類靜態初始化塊中調用
<code>super()</code>
或使用參數物件是錯誤語法。
</p>
<p>
這些語句是同步計算的。您不能在此塊中使用
<code>await</code>
或
<code>yield</code>
。 (將初始化語句視為隱密地包裝在函數中。)
</p>
<p>
靜態塊的範圍嵌套在類主體的詞法範圍內,並且可以訪問類中聲明的私有名稱,而不會導致語法錯誤。
</p>
<p>
靜態欄位初始值設定項和靜態初始化塊是一一計算的。初始化塊可以引用其上方的欄位值,但不能引用其下方的欄位值。所有靜態方法都是預先添加的並且可以訪問,但如果它們引用當前塊下方的欄位,則調用它們可能不會按預期運行。
</p>
<div class="notecard">
<p>
<strong>備註:</strong>
這對於私有靜態欄位更為重要,因為訪問未初始化的私有欄位會引發
TypeError,即使私有欄位在下面聲明也是如此。
(如果未聲明私有欄位,則會出現早期語法錯誤。)
</p>
</div>
<p>靜態初始化塊可能沒有裝飾器(類本身可以)。</p>
<h3>範例</h3>
<h3>Multiple blocks</h3>
<p>
下面的代碼演示了一個具有靜態初始化塊和交錯靜態欄位初始值設定項的類。輸出顯示塊和欄位是按執行順序計算的。
</p>
<pre><code class="language-js">
class MyClass {
static field1 = console.log("static field1");
static {
console.log("static block1");
}
static field2 = console.log("static field2");
static {
console.log("static block2");
}
}
// 'static field1'
// 'static block1'
// 'static field2'
// 'static block2'
</code></pre>
<p>請注意,超類的任何靜態初始化都會先執行,然後再執行其子類。</p>
<h3>Using this and super</h3>
<p>
靜態塊中的
<code>this</code>
指的是該類的構造函數物件。此代碼顯示如何訪問公共靜態欄位。
</p>
<pre><code class="language-js">
class A {
static field = "static field";
static {
console.log(this.field);
}
}
// 'static field'
</code></pre>
<p>
<code>super.property</code>
語法可以在靜態塊內使用來引用超類的靜態屬性。
</p>
<pre><code class="language-js">
class A {
static field = "static field";
}
class B extends A {
static {
console.log(super.field);
}
}
// 'static field'
</code></pre>
<h3>Access to private properties</h3>
<p>
下面的範例顯示瞭如何從類外部的物件授予對類的私有實例欄位的訪問權限(範例來自
<a
href="https://v8.dev/features/class-static-initializer-blocks#access-to-private-fields"
class="external"
target="_blank"
>
v8.dev blog
</a>
):
</p>
<pre><code class="language-js">
let getDPrivateField;
class D {
#privateField;
constructor(v) {
this.#privateField = v;
}
static {
getDPrivateField = (d) => d.#privateField;
}
}
console.log(getDPrivateField(new D("private"))); // 'private'
</code></pre>
<p>資料來源:</p>
<p>
<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Static_initialization_blocks"
>
https://developer.mozilla.org/.../Static_initialization_blocks
</a>
</p>
<p>
<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static"
>
https://developer.mozilla.org/.../Classes#static
</a>
</p>
</article>
</main>
</body>
<script type="module" src="./js/main.js"></script>
</html>