aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/statements/switch/index.html
blob: 763bda116b2291b377a79fb8041fdae4e186a6f7 (plain)
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
---
title: switch
slug: Web/JavaScript/Reference/Statements/switch
tags:
  - JavaScript
  - Reference
  - Statement
  - Web
  - 参考
  - 声明
translation_of: Web/JavaScript/Reference/Statements/switch
---
<div>{{jsSidebar("Statements")}}</div>

<p><strong><code>switch</code> 语句</strong>评估一个<a href="/zh-CN/docs/Web/JavaScript/Guide/Expressions_and_Operators">表达式</a>,将表达式的值与<code>case</code>子句匹配,并执行与该情况相关联的<a href="/zh-CN/docs/Web/JavaScript/Reference/Statements">语句</a></p>

<div>{{EmbedInteractiveExample("pages/js/statement-switch.html")}}</div>



<h2 id="语法">语法</h2>

<pre class="brush: js">switch (expression) {
  case value1:
    // 当 expression 的结果与 value1 匹配时,执行此处语句
    [break;]
  case value2:
    // 当 expression 的结果与 value2 匹配时,执行此处语句
    [break;]
  ...
  case valueN:
    // 当 expression 的结果与 valueN 匹配时,执行此处语句
    [break;]
  [default:
    // 如果 expression 与上面的 value 值都不匹配,执行此处语句
    [break;]]
}</pre>

<dl>
 <dt><code>expression</code></dt>
 <dd>一个用来与 case 子语句匹配的表达式。</dd>
 <dt><code>case valueN</code> {{optional_inline}}</dt>
 <dd>用于匹配 <code>expression</code><code>case</code> 子句。如果 <code>expression</code> 与给定的 <code>valueN</code> 相匹配,则执行该 case 子句中的语句直到该 <code>switch</code> 语句结束或遇到一个 <code>break</code></dd>
 <dt><code>default</code> {{optional_inline}}</dt>
 <dd>一个 <code>default</code> 子句;如果给定,这条子句会在 <code>expression</code> 的值与任一 <code>case</code> 语句均不匹配时执行。</dd>
</dl>

<h2 id="描述">描述</h2>

<p>一个 switch 语句首先会计算其 expression 。然后,它将从第一个 case 子句开始直到寻找到一个其表达式值与所输入的 expression 的值所相等的子句(使用 <a href="/zh-CN/docs/Web/JavaScript/Reference/Operators/Comparison_Operators">严格运算符</a><code>===</code>)并将控制权转给该子句,执行相关语句。(如果多个 case 与提供的值匹配,则选择匹配的第一个 case,即使这些 case 彼此间并不相等。)</p>

<p>如果没有 <code>case</code> 子句相匹配,程序则会寻找那个可选的 <code>default</code> 子句,如果找到了,将控制权交给它,执行相关语句。若没有 <code>default</code> 子句,程序将继续执行直到 <code>switch</code> 结束。按照惯例,<code>default</code> 子句是最后一个子句,不过也不需要这样做。</p>

<p>可选的 <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/break" title="JavaScript/Reference/Statements/break">break</a></code> 语句确保程序立即从相关的 case 子句中跳出 switch 并接着执行 switch 之后的语句。若 <code>break</code> 被省略,程序会继续执行 <code>switch</code> 语句中的下一条语句。</p>

<h2 id="示例">示例</h2>

<h3 id="使用_switch">使用 <code>switch</code></h3>

<p>下面的例子中,如果 <code>expr</code> 计算为 "Bananas",程序就会匹配值为 "Bananas" 的 case 然后执行相关语句。当遇到 <code>break</code> 时,程序就跳出 <code>switch</code> 然后执行 <code>switch</code> 后的语句。若 <code>break</code> 被省略,值为 "Cherries" 的 case 中的语句就也将被执行。</p>

<pre class="brush: js">switch (expr) {
  case 'Oranges':
    console.log('Oranges are $0.59 a pound.');
    break;
  case 'Apples':
    console.log('Apples are $0.32 a pound.');
    break;
  case 'Bananas':
    console.log('Bananas are $0.48 a pound.');
    break;
  case 'Cherries':
    console.log('Cherries are $3.00 a pound.');
    break;
  case 'Mangoes':
  case 'Papayas':
    console.log('Mangoes and papayas are $2.79 a pound.');
    break;
  default:
    console.log('Sorry, we are out of ' + expr + '.');
}

console.log("Is there anything else you'd like?");
</pre>

<h3 id="如果忘记_break_会怎么样?">如果忘记 break 会怎么样?</h3>

<p>如果你忘记添加 break,那么代码将会从值所匹配的 case 语句开始运行,然后持续执行下一个 case 语句而不论值是否匹配。例子如下:</p>

<pre class="brush: js">var foo = 0;
switch (foo) {
  case -1:
    console.log('negative 1');
    break;
  case 0: // foo 的值为 0 所以匹配这里所以这一块会运行
    console.log(0);
    // 注意:那个没写的 break 原本在这儿
  case 1: // 'case 0:' 里没有 break 语句所以这个 case 也会运行
    console.log(1);
    break; // 遇到了 break,所以不会再继续进入 'case 2:' 了
  case 2:
    console.log(2);
    break;
  default:
    console.log('default');
}</pre>

<h3 id="我能把_default_放到_case_之间吗?">我能把 default 放到 case 之间吗?</h3>

<p>可以啊!JavaScript 会在它找不到匹配项时跳回到那个 default :</p>

<pre class="brush: js">var foo = 5;
switch (foo) {
  case 2:
    console.log(2);
    break; // 遇到 break,所以不会继续进入 'default:'
  default:
    console.log('default')
    // 掉到下面
  case 1:
    console.log('1');
}
</pre>

<p>即使你把 default 放到其它 case 之上,它仍有效。</p>

<h3 id="使用多准则_case_的方法">使用多准则 case 的方法</h3>

<p>这个技术来源于此:</p>

<p><a href="http://stackoverflow.com/questions/13207927/switch-statement-multiple-cases-in-javascript">Switch statement multiple cases in JavaScript (Stack Overflow)</a></p>

<h4 id="多_case_-_单一操作">多 case - 单一操作</h4>

<p>这种方法利用这样一个事实:如果 case 语句之下没有 break ,它将继续执行下一个 case 语句,而不管 case 是否符合条件。 请看“如果忘记 break 会怎么样?”部分。</p>

<p>这是一个单操作顺序的 switch 语句,其中四个不同值的执行结果完全一样。</p>

<pre class="brush: js">var Animal = 'Giraffe';
switch (Animal) {
  case 'Cow':
  case 'Giraffe':
  case 'Dog':
  case 'Pig':
    console.log('This animal will go on Noah\'s Ark.');
    break;
  case 'Dinosaur':
  default:
    console.log('This animal will not.');
}</pre>

<h4 id="多_case_-_关联操作">多 case - 关联操作</h4>

<p>这是一个关联操作顺序的 switch 语句,其中,根据所输入的整数,你会得到不同的输出。这表示它将以你放置 case 语句的顺序遍历,并且不必是数字顺序的。在 JavaScript 中,你甚至可以将字符串定义到这些 case 语句里。</p>

<pre class="brush: js">var foo = 1;
var output = 'Output: ';
switch (foo) {
  case 0:
    output += 'So ';
  case 1:
    output += 'What ';
    output += 'Is ';
  case 2:
    output += 'Your ';
  case 3:
    output += 'Name';
  case 4:
    output += '?';
    console.log(output);
    break;
  case 5:
    output += '!';
    console.log(output);
    break;
  default:
    console.log('Please pick a number from 0 to 5!');
}</pre>

<p>这个例子的输出:</p>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Value</th>
   <th scope="col">Log text</th>
  </tr>
  <tr>
   <td>foo is NaN or not 1, 2, 3, 4, 5 or 0</td>
   <td>Please pick a number from 0 to 5!</td>
  </tr>
  <tr>
   <td>0</td>
   <td>Output: So What Is Your Name?</td>
  </tr>
  <tr>
   <td>1</td>
   <td>Output: What Is Your Name?</td>
  </tr>
  <tr>
   <td>2</td>
   <td>Output: Your Name?</td>
  </tr>
  <tr>
   <td>3</td>
   <td>Output: Name?</td>
  </tr>
  <tr>
   <td>4</td>
   <td>Output: ?</td>
  </tr>
  <tr>
   <td>5</td>
   <td>Output: !</td>
  </tr>
 </tbody>
</table>

<h3 id="switch_语句内的块级作用域"><code>switch</code> 语句内的块级作用域</h3>

<p>随着绝大多数现代浏览器已支持 ECMAScript 2015 (ES6),在某些场景下您可能需要使用 <a href="/en-US/docs/Web/JavaScript/Reference/Statements/let">let</a><a href="/en-US/docs/Web/JavaScript/Reference/Statements/const">const</a> 语句,以在块级作用域内声明变量。</p>

<p>以这段代码为例:</p>

<pre class="brush: js">const action = 'say_hello';
switch (action) {
  case 'say_hello':
    let message = 'hello';
           console.log('0 ~5');
           break;
  case 'say_hi':
    let message = 'hi';
    case 6: console.log('6');
    break;
  default:
    console.log('Empty action received.');
    break;
}</pre>

<p>这个示例会导致意想不到的错误 <code>Uncaught SyntaxError: Identifier 'message' has already been declared</code>.</p>

<p>这是因为第一个 <code>let message = 'hello';</code> 与第二个 <code>let message = 'hi';</code> 语句产生了冲突,虽然他们处于各自分隔的 case 语句中,即 <code>case 'say_hello':</code> 和 <code>case 'say_hi':</code>。导致这一问题的根本原因在于两个 <code>let</code> 语句处于同一个块级作用域,所以它们被认为是同一个变量名的重复声明。</p>

<p>通过把 case 语句包装到括号里面,我们就可以轻松解决这个问题。</p>

<pre class="brush: js">const action = 'say_hello';
switch (action) {
  case 'say_hello': { // added brackets
    let message = 'hello';
    console.log(message);
    break;
  } // added brackets
  case 'say_hi': { // added brackets
    let message = 'hi';
    console.log(message);
    break;
  } // added brackets
  default: { // added brackets
    console.log('Empty action received.');
    break;
  } // added brackets
}</pre>

<p>此时,这段代码就会在控制台输出 <code>hello</code>,不会再有任何报错。</p>

<h2 id="规范">规范</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('ES3')}}</td>
   <td>{{Spec2('ES3')}}</td>
   <td>Initial definition. Implemented in JavaScript 1.2</td>
  </tr>
  <tr>
   <td>{{SpecName('ES5.1', '#sec-12.11', 'switch statement')}}</td>
   <td>{{Spec2('ES5.1')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-switch-statement', 'switch statement')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-switch-statement', 'switch statement')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="浏览器兼容性">浏览器兼容性</h2>



<p>{{Compat("javascript.statements.switch")}}</p>

<h2 id="相关链接">相关链接</h2>

<ul>
 <li><a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/if...else"><code>if...else</code></a></li>
</ul>