<dl id="r7hd5"><delect id="r7hd5"></delect></dl>
<dl id="r7hd5"><i id="r7hd5"><font id="r7hd5"></font></i></dl><dl id="r7hd5"><i id="r7hd5"><meter id="r7hd5"></meter></i></dl>
<video id="r7hd5"></video><dl id="r7hd5"><delect id="r7hd5"></delect></dl>
<dl id="r7hd5"><delect id="r7hd5"></delect></dl><dl id="r7hd5"></dl>
<video id="r7hd5"></video> <video id="r7hd5"></video><dl id="r7hd5"></dl><dl id="r7hd5"><i id="r7hd5"><meter id="r7hd5"></meter></i></dl>
<dl id="r7hd5"><i id="r7hd5"></i></dl>
<dl id="r7hd5"></dl><dl id="r7hd5"></dl>
<video id="r7hd5"><i id="r7hd5"></i></video><dl id="r7hd5"></dl><dl id="r7hd5"></dl>
<video id="r7hd5"><i id="r7hd5"><delect id="r7hd5"></delect></i></video>
<i id="r7hd5"></i>
<video id="r7hd5"></video>
<dl id="r7hd5"><delect id="r7hd5"></delect></dl>
溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JS語法有C#的switch表達式

發布時間:2023-07-17 13:50:26 來源:億速云 閱讀:63 作者:栢白 欄目:開發技術

今天小編給大家分享的是JS語法有C#的switch表達式,相信很多人都不太了解,為了讓大家更加了解,所以給大家總結了以下內容,一起往下看吧。一定會有所收獲的哦。


于 C/Java 語系的語言,都有 switch 語法。switch 語法用于多分支是一個標準的用法,但這個分支語法的各分支之間存在穿透性,所以需要 break 來切斷邏輯,這也成為 switch 語法中最重要的一個替在缺陷來源。此外,由于 switch 語句中各 case 的代碼是在同一個作用域中,也會對代碼造成一些不便。

C# 8.0 引入了 switch 表達式。C# 的 switch 表達式有著非常豐富的語法元素,可以和模式匹配和解構等語法元素協同工作 &mdash;&mdash; 這些都不在這里細說,但是對傳統的 switch 語句 進行了一些改進:

  • 通過箭頭 (=>) 標記處理了 case 和語句之間的一對一關系,不需要 break,不再穿透;

  • 作為表達式,可以而且必須返回值;

新的約束

  • switch 表達式一定要詳盡(邏輯一定會走進某一個 case,可以通過棄元模式兜底),否則可能會在運行時引發異常。

在 C# 8.0 發布的同年,Java 12 也發布并引入了 switch 表達式預覽。Java 的 switch 表達式實現比較簡單,就是 switch 語句到 switch 表達式的直接轉換,僅支持等值匹配。直到 2023 年 3 月 Java 20 發布,switch 表達式才開始支持模式匹配。相比之下,Kotlin 的 when 表達式走在了前面。

在這個問題上 JavaScript 似乎走在了后面,不過在語言提供 switch 表達式之前,我們可以嘗試自己造個輪子。

思路當然是參考策略模式。假設有一個列表,這個列表里的每個元素都包含了兩個因素:第一個用于判斷是否命中,第二個是個函數,得到一個計算結果。然后寫一個循環遍歷列表的每個元素,一旦某個元素命中,就執行元素攜帶的函數獲得結果,中斷循環,返回結果。如果列表的最后一個元素必定命中,那么這個列表就是“詳盡”的。

when 函數寫法

那么這個 when 函數可能會這樣寫(switch 是關鍵字,所以使用 when 來作為函數名):

// JS
function when(value, ...cases) {
    for (const { is, run } of cases) {
        if (is(value)) {
            return run(value);
        }
    }
    throw new Error("非詳盡");
}

這里我們假設每個情況 (case) 都含有 is 方法用于判斷是否命中,用 run 方法保存命中后需要執行的操作。

分算等級”測試

相應地,我們可以經典的“拿分算等級”來進行測試:

// JS
function calcGrade(score) {
    return when(
        score,
        { is: v => v >= 0 && v < 80, run: v => `不合格 (${v})` },
        { is: v => v >= 80 && v < 100, run: v => `合格 (${v})` },
        { is: v => v == 100, run: v => `滿分 (${v})` },
        { is: _ => true, run: v => `無效 (${v})` },
    );
}
for (let i = 0; i < 50; i++) {
    const v = 70 + ~~(Math.random() * 35);
    console.log(calcGrade(v));
}

在 calcGrade 實現中 when 的 case 列表最后一項采用了“永真”斷言,所以走到這一項的時候一定會命中,從邏輯上來永遠不會觸發 Error。如果是非“詳盡”的情況列表,就有可能觸發 Error。

測試問題

不過現在從測試代碼中就發現了兩個問題:

  • is 斷言是采用函數的形式,不能簡單地直接按值匹配;

  • 從調用形式上來說,score 和后面的 case 元素是同級的,形式上區分不明顯;

  • 每次都要寫 is 和 run,條件多了寫起來也煩。

繼續改進 &mdash;&mdash;

// JS
function when(value) {
    // when 的參數先給 switch 的值
    // 返回一個函數來處理分支匹配 ②
    return function (...cases) {
        for (const [is, run] of cases) {
//                 ^^^^^^^^^ 從對象改為元組(數組)③
            if (value === is || (typeof is == "function" && is(value))) {
//                    ^^^^^^ 精確判斷 ①
//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 斷言函數判斷
                return  run(value);
//                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 可指定行為(函數)
            }
        }
        throw new Error("非詳盡");
    };
}
function calcGrade(score) {
    return when(score)(
//         ^^^^^^^^^^^ 這里返回的是匹配處理的函數
        [v => v >= 0 && v < 80, v => `不合格 (${v})`],
        [v => v >= 80 && v < 100, v => `合格 (${v})`],
        [100, () => "滿分 (100)"],
//       ^^^ 可以指定匹配的值
//            ^^ 計算不需要參數,可以不聲明
        [_ => true, v => `無效 (${v})`],
//       ^^^^^^^^^ 兜底的永真斷言
    );
}

為什么兜底斷言必須使用一個函數呢?因為 true 值也有可能是對應一種預想的分支情況。由于這個 when 是通過語義來實現而不是通過語法來實現的,所以這里沒辦法定義一個安全的兜底斷言語法,只有用斷言函數會相對安全。

升級成 TypeScript

至此為止我們已經基本實現了 switch 表達式 (when),把它升級成 TypeScript

// TypeScript
type CaseCondition<T> = T extends Function ? never : ((t: T) => boolean) | T
type Case<T, R> = [CaseCondition<T>, (t: T) => R];
function when<T>(value: T): <R>(...cases: Case<T, R>[]) => R {
    return function<R>(...cases: Case<T, R>[]): R {
        for (const [is, run] of cases) {
            if (value === is || (typeof is == "function" && is(value))) {
                return run(value);
            }
        }
        throw new Error("非詳盡");
    };
}
function calcGrade(score: number) {
    return when(score)(
        [v => v >= 0 && v < 80, v => `不合格 (${v})`],
        [v => v >= 80 && v < 100, v => `合格 (${v})`],
        [100, () => "滿分 (100)"],
        [_ => true, v => `無效 (${v})`],
    );
}

這段代碼當然可以直接用,但是如果使用 npm 可能會更方便一點:

npm install @jamesfancy/when
// TypeScript
import { when } from "@jamesfancy/when";
function calcGrade(score: number) {
    return when(score)(
        [v => v >= 0 && v < 80, v => `不合格 (${v})`],
        [v => v >= 80 && v < 100, v => `合格 (${v})`],
        [100, () => "滿分 (100)"],
        [_ => true, v => `無效 (${v})`],
    );
}

關于JS語法有C#的switch表達式就分享到這里了,希望以上內容可以對大家有一定的參考價值,可以學以致用。如果喜歡本篇文章,不妨把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

国语自产精品视频_91超碰人人澡夜夜澡_欧美777精品久久久久网_97精品国产一区二区三区_久久婷婷大香萑太香蕉av 精品一久久香蕉国产线看观 无码草草草在线观看 国产v亚洲v天堂a无码 国产日韩一区二区三区免费高清 天天爽夜夜爽欧美精品视频 国产午夜福利在线观看红一片 国产午夜精品理论片 芒果一二三区乱码天天看隐藏入口 国产高清女人高潮对白 91久久精品日日躁
<dl id="r7hd5"><delect id="r7hd5"></delect></dl>
<dl id="r7hd5"><i id="r7hd5"><font id="r7hd5"></font></i></dl><dl id="r7hd5"><i id="r7hd5"><meter id="r7hd5"></meter></i></dl>
<video id="r7hd5"></video><dl id="r7hd5"><delect id="r7hd5"></delect></dl>
<dl id="r7hd5"><delect id="r7hd5"></delect></dl><dl id="r7hd5"></dl>
<video id="r7hd5"></video> <video id="r7hd5"></video><dl id="r7hd5"></dl><dl id="r7hd5"><i id="r7hd5"><meter id="r7hd5"></meter></i></dl>
<dl id="r7hd5"><i id="r7hd5"></i></dl>
<dl id="r7hd5"></dl><dl id="r7hd5"></dl>
<video id="r7hd5"><i id="r7hd5"></i></video><dl id="r7hd5"></dl><dl id="r7hd5"></dl>
<video id="r7hd5"><i id="r7hd5"><delect id="r7hd5"></delect></i></video>
<i id="r7hd5"></i>
<video id="r7hd5"></video>
<dl id="r7hd5"><delect id="r7hd5"></delect></dl>