前幾天幫同事看問題,要在 JavaScript 偵測 location.href 是否為 / 字元結尾,看到 Visual Studio 自動提示了 endsWith() 函式,大驚!

JavaScript 不知何時早已內建 startsWith、endsWith (Chrome 41 就有,目前版號都破百了),我居然還傻傻用 s.indexOf('/') == 0、s.lastIndexOf('/') == s.length -1 或是 /^\//.exec(s) 檢查。

我在瀏覽器寫法 JavaScript 一向很保守,這跟我一直在維護 IE 古蹟有關,看到新語法往往潛意識會跳過,因為即使在 IE11 都未必支援(未來也不會支援,因為 IE 沒有未來了),知道好方法又不能用更痛苦 XD。像開頭提到的 startsWith(),就不在 IE 支援之列:參考

為避免程式用新語法在 IE 爆炸,老寫法笨歸笨,但保證相容,造就我不熱衷學習 JavaScript 新語法的心態。如今,野生 IE 即將滅絕(將於 2022/6/15 EOS),企業內部人工飼養 IE 預估可用到 2029 但應會漸以 Edge 為主或有 Chrome 並行 (延伸閱讀:古蹟維護小組觀點 - IE 大限揭曉,這下總算 封印解除 ,可以大方使用新一代的前端技術惹。


(照片作者:Evan)

這次事件讓我想到該重新檢視 JavaScript API,看看這些年自己因為 IE 錯過哪些好用的新方法,就從字串開始吧。

要查 String 有哪些 API,當然是看 MDN 囉!

看了一輪 String 方法列表,跳過用到爛的 indexOf、lastIndexOf、toUpperCase、substr、substring,聚焦我不熟或遺漏隱藏用法的項目,整理範例如下:

<!DOCTYPE html>
<html>
    <head>
        <style>
            .t { 
                display: inline-block; width: 100px; padding: 3px;
                color: white; background-color: cornflowerblue;
                text-align: right; margin-bottom: 2px;
            }
        </style>
    </head>
    <body>
        <pre id="d"></pre>
        <script>
            function log(t, m) {
                document.getElementById('d').innerHTML +=
                    `<span class=t>${t}</span> <span>${m}</span>` + '\n';
            }
            function logEval(t, exp) {
                log(t, exp + ` => ${eval(exp)}`);
            }
            const s = "This is a book.";
            log('string', `let s="${s}"`);
            // at() 取第 n 個字元,類似 charAt 但可用負數
            logEval('at()', `s.at(2)`); 
            logEval('at()', `s.at(-5)`);
            // charCodeAt() 取第 n 個字元的 UTF-16(ASCII) 碼
            logEval('charAt()', `s.charAt(2) + "->" + s.charCodeAt(2)`);
            // codePointAt() 可用轉換成 &#160; 
            const c = '\ua66c';
            const unicodeCodePoint = c.codePointAt(0);
            log('codePointAt()', `${c} -> &amp;#${unicodeCodePoint}; &#${unicodeCodePoint};`);
            logEval('concat()', `"hello".concat(" ", "world", "!")`);
            // 相當於 C# string.Contains()
            logEval('includes()', `"Smiles".includes("mile")`)
            logEval('startsWith()', `"darkthread".startsWith("dark")`);
            logEval('endsWith()', `"darkthread".endsWith("a")`);
            logEval('match()', `JSON.stringify("192.168.1.1".match(/\\d{1,3}/))`);
            logEval('match()', `JSON.stringify("192.168.1.1".match(/\\d{1,3}/g))`);
            // 數字補零很好用
            logEval('padStart()', `"12345".padStart(7, '0')`);
            logEval('padEnd()', `"1234".padEnd(7, "#")`);
            logEval('repeat()', `"A".repeat(10)`);
            logEval('replace()', `"A1B2C3D4E5".replace("B2", "")`);
            logEval('replace()', `"A1B2C3D4E5".replace(/[a-z]/ig, "")`);
            logEval('search()', `"secret number 123 inside".search(/\\d/)`);
            logEval('slice()', `"pen pineapple apple pen".slice(4)`);
            logEval('slice()', `"pen pineapple apple pen".slice(-3)`);
            logEval('slice()', `"pen pineapple apple pen".slice(4, 7)`);
            logEval('split()', `"pen pineapple apple pen".split(' ')`);
            // trim* 只去除空白,去頭尾非空白字元要用 replace + regular expression
            logEval('trim()', `"[" + "  HELLO    ".trim() + "]"`);
            logEval('trimStart()', `"[" + "  HELLO    ".trimStart() + "]"`);
            logEval('trimEnd()', `"[" + "  HELLO    ".trimEnd() + "]"`);
            logEval('Trim ending /', `"~/subdir/".replace(/\\/$/g, '')`);
            // String("1+2") 與 "1+2" 行為有些不同,
            logEval('valueOf()', `typeof(new String("1+2"))`);
            logEval('valueOf()', `eval(new String("1+2"))`);
            logEval('valueOf()', `new String("1+2").valueOf()`);
            logEval('valueOf()', `eval(new String("1+2").valueOf())`);           
        </script>
    </body>
</html>

檢閱完畢。

Needing to support IE, I missed some JavaScript handy methods. This notes enumerate the functions I missed in these years.


Comments

# by Huang

一看到IDE有提示就可以用了

# by slash

寫了20年的程式,我也覺得JS的substring()何須看文件,就不信還能變出甚麼花樣?直到那天我膝蓋中了一箭...

Post a comment