JavaScript 假如default不是switch的最后一項
話說大家對于switch語句應該再熟悉不過了,各種類C語言都不例外,JavaScript自然也是如此。switch的邏輯很簡單,根據switch內容的值執(zhí)行對應的case項,否則執(zhí)行default項即可。但是不同的語言在具體一些細節(jié)上面的處理卻是不同的。
例如在JavaScript里,每個case項都可以沒有break,于是語句便會順延到下個case或是default里面去——但某些語言設計者認為這種特性容易造成代碼理解上的偏差,因此比如在C#里便要求每個case都要有個break。那么再來一個細節(jié)問題:如果default之后還有case,那么會出現什么樣的情況?如果default里沒有break呢?
- switch (a)
- {
- case 0:
- console.log("0");
- default:
- console.log("default");
- case 1:
- console.log("1");
- }
就好比這段代碼,當a等于0、1或2的時候,將會輸出什么樣的內容呢?先猜猜,別急著往下看。
當a等于0時,則會輸出:
- 0
- default
- 1
當a等于1時,則會輸出:
- 1
當a等于2時,則會輸出:
- default
- 1
好吧,盡管這樣的代碼比較罕見,但執(zhí)行結果也并沒有什么“特殊”的。switch的規(guī)則依舊可以用一句話說清:如果匹配到某個case,則從該case處開始執(zhí)行,否則就從default處開始執(zhí)行,一直向下,直到出現break語句為止。至于default的位置是否在***,對于執(zhí)行的策略可謂完全沒有影響。
當然,我實在沒想到為什么有人會寫這樣的代碼,所以假如有人對這點感覺恍惚我也覺得沒太大關系。不過既然我要寫Jscex,則還是必須對此類代碼的行為有所了解。盡管語言的使用者可以選擇合適的子集,但語言的開發(fā)者(編譯器、解釋器等等)卻必須遵循完整的規(guī)范,這是Jscex這類項目需要應對的麻煩。
既然Jscex號稱支持“全部JavaScript語言特性”,自然對switch的支持也在包括在內。switch的麻煩之處在于它的每個分支不像if語句那樣完全相互獨立,而是會不斷“穿透”下去直至遇上break。因此Jscex在處理switch的時候也使用了一些技巧。例如下面這段代碼:
- switch (a) {
- case 0:
- $await(helloWorld());
- default:
- console.log("default");
- case 1:
- console.log("1");
- }
Jscex會將每個case及default中的語句“補齊”,以“確保”每項里都有完整的語句以及***的break:
- switch (a) {
- case 0:
- $await(helloWorld());
- console.log("default");
- console.log("1");
- break;
- default:
- console.log("default");
- console.log("1");
- break;
- case 1:
- console.log("1");
- break;
- }
然后再將其編譯為:
- switch (a) {
- case 0:
- return $$_builder_$$_0.Bind(helloWorld(), function () {
- console.log("default");
- console.log("1");
- return $$_builder_$$_0.Normal();
- });
- default:
- console.log("default");
- console.log("1");
- return $$_builder_$$_0.Normal();
- case 1:
- console.log("1");
- return $$_builder_$$_0.Normal();
- }
- })
自然,如果switch里沒有包含bind操作(例如$await語句),則整個switch語句都會得以保留,這也是Jscex編譯結果的優(yōu)化策略之一。
原文地址:http://blog.zhaojie.me/2011/05/javascript-when-break-is-not-the-last-choice-of-switch.html
【編輯推薦】