2

這些年,我錯過的 JavaScript 字串函數

 2 years ago
source link: https://blog.darkthread.net/blog/js-string-funcs-notes/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

這些年,我錯過的 JavaScript 字串函數

2022-04-17 09:20 AM 1 1,335

前幾天幫同事看問題,要在 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() 可用轉換成   
            const c = '\ua66c';
            const unicodeCodePoint = c.codePointAt(0);
            log('codePointAt()', `${c} -> &#${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>

檢閱完畢。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK