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