<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 字符串的新增方法 本章介紹字符串對象的新增方法。 ## String.fromCodePoint() ES5 提供`String.fromCharCode()`方法,用于從 Unicode 碼點返回對應字符,但是這個方法不能識別碼點大于`0xFFFF`的字符。 ```javascript String.fromCharCode(0x20BB7) // "?" ``` 上面代碼中,`String.fromCharCode()`不能識別大于`0xFFFF`的碼點,所以`0x20BB7`就發生了溢出,最高位`2`被舍棄了,最后返回碼點`U+0BB7`對應的字符,而不是碼點`U+20BB7`對應的字符。 ES6 提供了`String.fromCodePoint()`方法,可以識別大于`0xFFFF`的字符,彌補了`String.fromCharCode()`方法的不足。在作用上,正好與下面的`codePointAt()`方法相反。 ```javascript String.fromCodePoint(0x20BB7) // "??" String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y' // true ``` 上面代碼中,如果`String.fromCodePoint`方法有多個參數,則它們會被合并成一個字符串返回。 注意,`fromCodePoint`方法定義在`String`對象上,而`codePointAt`方法定義在字符串的實例對象上。 ## String.raw() ES6 還為原生的 String 對象,提供了一個`raw()`方法。該方法返回一個斜杠都被轉義(即斜杠前面再加一個斜杠)的字符串,往往用于模板字符串的處理方法。 ```javascript String.raw`Hi\n${2+3}!` // 實際返回 "Hi\\n5!",顯示的是轉義后的結果 "Hi\n5!" String.raw`Hi\u000A!`; // 實際返回 "Hi\\u000A!",顯示的是轉義后的結果 "Hi\u000A!" ``` 如果原字符串的斜杠已經轉義,那么`String.raw()`會進行再次轉義。 ```javascript String.raw`Hi\\n` // 返回 "Hi\\\\n" String.raw`Hi\\n` === "Hi\\\\n" // true ``` `String.raw()`方法可以作為處理模板字符串的基本方法,它會將所有變量替換,而且對斜杠進行轉義,方便下一步作為字符串來使用。 `String.raw()`本質上是一個正常的函數,只是專用于模板字符串的標簽函數。如果寫成正常函數的形式,它的第一個參數,應該是一個具有`raw`屬性的對象,且`raw`屬性的值應該是一個數組,對應模板字符串解析后的值。 ```javascript // `foo${1 + 2}bar` // 等同于 String.raw({ raw: ['foo', 'bar'] }, 1 + 2) // "foo3bar" ``` 上面代碼中,`String.raw()`方法的第一個參數是一個對象,它的`raw`屬性等同于原始的模板字符串解析后得到的數組。 作為函數,`String.raw()`的代碼實現基本如下。 ```javascript String.raw = function (strings, ...values) { let output = ''; let index; for (index = 0; index < values.length; index++) { output += strings.raw[index] + values[index]; } output += strings.raw[index] return output; } ``` ## 實例方法:codePointAt() JavaScript 內部,字符以 UTF-16 的格式儲存,每個字符固定為`2`個字節。對于那些需要`4`個字節儲存的字符(Unicode 碼點大于`0xFFFF`的字符),JavaScript 會認為它們是兩個字符。 ```javascript var s = "??"; s.length // 2 s.charAt(0) // '' s.charAt(1) // '' s.charCodeAt(0) // 55362 s.charCodeAt(1) // 57271 ``` 上面代碼中,漢字“??”(注意,這個字不是“吉祥”的“吉”)的碼點是`0x20BB7`,UTF-16 編碼為`0xD842 0xDFB7`(十進制為`55362 57271`),需要`4`個字節儲存。對于這種`4`個字節的字符,JavaScript 不能正確處理,字符串長度會誤判為`2`,而且`charAt()`方法無法讀取整個字符,`charCodeAt()`方法只能分別返回前兩個字節和后兩個字節的值。 ES6 提供了`codePointAt()`方法,能夠正確處理 4 個字節儲存的字符,返回一個字符的碼點。 ```javascript let s = '??a'; s.codePointAt(0) // 134071 s.codePointAt(1) // 57271 s.codePointAt(2) // 97 ``` `codePointAt()`方法的參數,是字符在字符串中的位置(從 0 開始)。上面代碼中,JavaScript 將“??a”視為三個字符,codePointAt 方法在第一個字符上,正確地識別了“??”,返回了它的十進制碼點 134071(即十六進制的`20BB7`)。在第二個字符(即“??”的后兩個字節)和第三個字符“a”上,`codePointAt()`方法的結果與`charCodeAt()`方法相同。 總之,`codePointAt()`方法會正確返回 32 位的 UTF-16 字符的碼點。對于那些兩個字節儲存的常規字符,它的返回結果與`charCodeAt()`方法相同。 `codePointAt()`方法返回的是碼點的十進制值,如果想要十六進制的值,可以使用`toString()`方法轉換一下。 ```javascript let s = '??a'; s.codePointAt(0).toString(16) // "20bb7" s.codePointAt(2).toString(16) // "61" ``` 你可能注意到了,`codePointAt()`方法的參數,仍然是不正確的。比如,上面代碼中,字符`a`在字符串`s`的正確位置序號應該是 1,但是必須向`codePointAt()`方法傳入 2。解決這個問題的一個辦法是使用`for...of`循環,因為它會正確識別 32 位的 UTF-16 字符。 ```javascript let s = '??a'; for (let ch of s) { console.log(ch.codePointAt(0).toString(16)); } // 20bb7 // 61 ``` 另一種方法也可以,使用擴展運算符(`...`)進行展開運算。 ```javascript let arr = [...'??a']; // arr.length === 2 arr.forEach( ch => console.log(ch.codePointAt(0).toString(16)) ); // 20bb7 // 61 ``` `codePointAt()`方法是測試一個字符由兩個字節還是由四個字節組成的最簡單方法。 ```javascript function is32Bit(c) { return c.codePointAt(0) > 0xFFFF; } is32Bit("??") // true is32Bit("a") // false ``` ## 實例方法:normalize() 許多歐洲語言有語調符號和重音符號。為了表示它們,Unicode 提供了兩種方法。一種是直接提供帶重音符號的字符,比如`ǒ`(\u01D1)。另一種是提供合成符號(combining character),即原字符與重音符號的合成,兩個字符合成一個字符,比如`O`(\u004F)和`ˇ`(\u030C)合成`ǒ`(\u004F\u030C)。 這兩種表示方法,在視覺和語義上都等價,但是 JavaScript 不能識別。 ```javascript '\u01D1'==='\u004F\u030C' //false '\u01D1'.length // 1 '\u004F\u030C'.length // 2 ``` 上面代碼表示,JavaScript 將合成字符視為兩個字符,導致兩種表示方法不相等。 ES6 提供字符串實例的`normalize()`方法,用來將字符的不同表示方法統一為同樣的形式,這稱為 Unicode 正規化。 ```javascript '\u01D1'.normalize() === '\u004F\u030C'.normalize() // true ``` `normalize`方法可以接受一個參數來指定`normalize`的方式,參數的四個可選值如下。 - `NFC`,默認參數,表示“標準等價合成”(Normalization Form Canonical Composition),返回多個簡單字符的合成字符。所謂“標準等價”指的是視覺和語義上的等價。 - `NFD`,表示“標準等價分解”(Normalization Form Canonical Decomposition),即在標準等價的前提下,返回合成字符分解的多個簡單字符。 - `NFKC`,表示“兼容等價合成”(Normalization Form Compatibility Composition),返回合成字符。所謂“兼容等價”指的是語義上存在等價,但視覺上不等價,比如“囍”和“喜喜”。(這只是用來舉例,`normalize`方法不能識別中文。) - `NFKD`,表示“兼容等價分解”(Normalization Form Compatibility Decomposition),即在兼容等價的前提下,返回合成字符分解的多個簡單字符。 ```javascript '\u004F\u030C'.normalize('NFC').length // 1 '\u004F\u030C'.normalize('NFD').length // 2 ``` 上面代碼表示,`NFC`參數返回字符的合成形式,`NFD`參數返回字符的分解形式。 不過,`normalize`方法目前不能識別三個或三個以上字符的合成。這種情況下,還是只能使用正則表達式,通過 Unicode 編號區間判斷。 ## 實例方法:includes(), startsWith(), endsWith() 傳統上,JavaScript 只有`indexOf`方法,可以用來確定一個字符串是否包含在另一個字符串中。ES6 又提供了三種新方法。 - **includes()**:返回布爾值,表示是否找到了參數字符串。 - **startsWith()**:返回布爾值,表示參數字符串是否在原字符串的頭部。 - **endsWith()**:返回布爾值,表示參數字符串是否在原字符串的尾部。 ```javascript let s = 'Hello world!'; s.startsWith('Hello') // true s.endsWith('!') // true s.includes('o') // true ``` 這三個方法都支持第二個參數,表示開始搜索的位置。 ```javascript let s = 'Hello world!'; s.startsWith('world', 6) // true s.endsWith('Hello', 5) // true s.includes('Hello', 6) // false ``` 上面代碼表示,使用第二個參數`n`時,`endsWith`的行為與其他兩個方法有所不同。它針對前`n`個字符,而其他兩個方法針對從第`n`個位置直到字符串結束。 ## 實例方法:repeat() `repeat`方法返回一個新字符串,表示將原字符串重復`n`次。 ```javascript 'x'.repeat(3) // "xxx" 'hello'.repeat(2) // "hellohello" 'na'.repeat(0) // "" ``` 參數如果是小數,會被取整。 ```javascript 'na'.repeat(2.9) // "nana" ``` 如果`repeat`的參數是負數或者`Infinity`,會報錯。 ```javascript 'na'.repeat(Infinity) // RangeError 'na'.repeat(-1) // RangeError ``` 但是,如果參數是 0 到-1 之間的小數,則等同于 0,這是因為會先進行取整運算。0 到-1 之間的小數,取整以后等于`-0`,`repeat`視同為 0。 ```javascript 'na'.repeat(-0.9) // "" ``` 參數`NaN`等同于 0。 ```javascript 'na'.repeat(NaN) // "" ``` 如果`repeat`的參數是字符串,則會先轉換成數字。 ```javascript 'na'.repeat('na') // "" 'na'.repeat('3') // "nanana" ``` ## 實例方法:padStart(),padEnd() ES2017 引入了字符串補全長度的功能。如果某個字符串不夠指定長度,會在頭部或尾部補全。`padStart()`用于頭部補全,`padEnd()`用于尾部補全。 ```javascript 'x'.padStart(5, 'ab') // 'ababx' 'x'.padStart(4, 'ab') // 'abax' 'x'.padEnd(5, 'ab') // 'xabab' 'x'.padEnd(4, 'ab') // 'xaba' ``` 上面代碼中,`padStart()`和`padEnd()`一共接受兩個參數,第一個參數是字符串補全生效的最大長度,第二個參數是用來補全的字符串。 如果原字符串的長度,等于或大于最大長度,則字符串補全不生效,返回原字符串。 ```javascript 'xxx'.padStart(2, 'ab') // 'xxx' 'xxx'.padEnd(2, 'ab') // 'xxx' ``` 如果用來補全的字符串與原字符串,兩者的長度之和超過了最大長度,則會截去超出位數的補全字符串。 ```javascript 'abc'.padStart(10, '0123456789') // '0123456abc' ``` 如果省略第二個參數,默認使用空格補全長度。 ```javascript 'x'.padStart(4) // ' x' 'x'.padEnd(4) // 'x ' ``` `padStart()`的常見用途是為數值補全指定位數。下面代碼生成 10 位的數值字符串。 ```javascript '1'.padStart(10, '0') // "0000000001" '12'.padStart(10, '0') // "0000000012" '123456'.padStart(10, '0') // "0000123456" ``` 另一個用途是提示字符串格式。 ```javascript '12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12" '09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12" ``` ## 實例方法:trimStart(),trimEnd() [ES2019](https://github.com/tc39/proposal-string-left-right-trim) 對字符串實例新增了`trimStart()`和`trimEnd()`這兩個方法。它們的行為與`trim()`一致,`trimStart()`消除字符串頭部的空格,`trimEnd()`消除尾部的空格。它們返回的都是新字符串,不會修改原始字符串。 ```javascript const s = ' abc '; s.trim() // "abc" s.trimStart() // "abc " s.trimEnd() // " abc" ``` 上面代碼中,`trimStart()`只消除頭部的空格,保留尾部的空格。`trimEnd()`也是類似行為。 除了空格鍵,這兩個方法對字符串頭部(或尾部)的 tab 鍵、換行符等不可見的空白符號也有效。 瀏覽器還部署了額外的兩個方法,`trimLeft()`是`trimStart()`的別名,`trimRight()`是`trimEnd()`的別名。 ## 實例方法:matchAll() `matchAll()`方法返回一個正則表達式在當前字符串的所有匹配,詳見《正則的擴展》的一章。 ## 實例方法:replaceAll() 歷史上,字符串的實例方法`replace()`只能替換第一個匹配。 ```javascript 'aabbcc'.replace('b', '_') // 'aa_bcc' ``` 上面例子中,`replace()`只將第一個`b`替換成了下劃線。 如果要替換所有的匹配,不得不使用正則表達式的`g`修飾符。 ```javascript 'aabbcc'.replace(/b/g, '_') // 'aa__cc' ``` 正則表達式畢竟不是那么方便和直觀,[ES2021](https://github.com/tc39/proposal-string-replaceall) 引入了`replaceAll()`方法,可以一次性替換所有匹配。 ```javascript 'aabbcc'.replaceAll('b', '_') // 'aa__cc' ``` 它的用法與`replace()`相同,返回一個新字符串,不會改變原字符串。 ```javascript String.prototype.replaceAll(searchValue, replacement) ``` 上面代碼中,`searchValue`是搜索模式,可以是一個字符串,也可以是一個全局的正則表達式(帶有`g`修飾符)。 如果`searchValue`是一個不帶有`g`修飾符的正則表達式,`replaceAll()`會報錯。這一點跟`replace()`不同。 ```javascript // 不報錯 'aabbcc'.replace(/b/, '_') // 報錯 'aabbcc'.replaceAll(/b/, '_') ``` 上面例子中,`/b/`不帶有`g`修飾符,會導致`replaceAll()`報錯。 `replaceAll()`的第二個參數`replacement`是一個字符串,表示替換的文本,其中可以使用一些特殊字符串。 - `$&`:匹配的子字符串。 - `` $` ``:匹配結果前面的文本。 - `$'`:匹配結果后面的文本。 - `$n`:匹配成功的第`n`組內容,`n`是從1開始的自然數。這個參數生效的前提是,第一個參數必須是正則表達式。 - `$$`:指代美元符號`$`。 下面是一些例子。 ```javascript // $& 表示匹配的字符串,即`b`本身 // 所以返回結果與原字符串一致 'abbc'.replaceAll('b', '$&') // 'abbc' // $` 表示匹配結果之前的字符串 // 對于第一個`b`,$` 指代`a` // 對于第二個`b`,$` 指代`ab` 'abbc'.replaceAll('b', '$`') // 'aaabc' // $' 表示匹配結果之后的字符串 // 對于第一個`b`,$' 指代`bc` // 對于第二個`b`,$' 指代`c` 'abbc'.replaceAll('b', `$'`) // 'abccc' // $1 表示正則表達式的第一個組匹配,指代`ab` // $2 表示正則表達式的第二個組匹配,指代`bc` 'abbc'.replaceAll(/(ab)(bc)/g, '$2$1') // 'bcab' // $$ 指代 $ 'abc'.replaceAll('b', '$$') // 'a$c' ``` `replaceAll()`的第二個參數`replacement`除了為字符串,也可以是一個函數,該函數的返回值將替換掉第一個參數`searchValue`匹配的文本。 ```javascript 'aabbcc'.replaceAll('b', () => '_') // 'aa__cc' ``` 上面例子中,`replaceAll()`的第二個參數是一個函數,該函數的返回值會替換掉所有`b`的匹配。 這個替換函數可以接受多個參數。第一個參數是捕捉到的匹配內容,第二個參數捕捉到是組匹配(有多少個組匹配,就有多少個對應的參數)。此外,最后還可以添加兩個參數,倒數第二個參數是捕捉到的內容在整個字符串中的位置,最后一個參數是原字符串。 ```javascript const str = '123abc456'; const regex = /(\d+)([a-z]+)(\d+)/g; function replacer(match, p1, p2, p3, offset, string) { return [p1, p2, p3].join(' - '); } str.replaceAll(regex, replacer) // 123 - abc - 456 ``` 上面例子中,正則表達式有三個組匹配,所以`replacer()`函數的第一個參數`match`是捕捉到的匹配內容(即字符串`123abc456`),后面三個參數`p1`、`p2`、`p3`則依次為三個組匹配。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看