1. ECMAScript 6 入門教程—字符串的新增方法

        共 5003字,需瀏覽 11分鐘

         ·

        2020-08-31 20:21

        作者 | 阮一峰

        1、String.fromCodePoint()
        ES5 提供String.fromCharCode()方法,用于從 Unicode 碼點(diǎn)返回對(duì)應(yīng)字符,但是這個(gè)方法不能識(shí)別碼點(diǎn)大于0xFFFF的字符。
        String.fromCharCode(0x20BB7)
        // "?"
        上面代碼中,String.fromCharCode()不能識(shí)別大于0xFFFF的碼點(diǎn),所以0x20BB7就發(fā)生了溢出,最高位2被舍棄了,最后返回碼點(diǎn)U+0BB7對(duì)應(yīng)的字符,而不是碼點(diǎn)U+20BB7對(duì)應(yīng)的字符。
        ES6 提供了String.fromCodePoint()方法,可以識(shí)別大于0xFFFF的字符,彌補(bǔ)了String.fromCharCode()方法的不足。在作用上,正好與下面的codePointAt()方法相反。
        String.fromCodePoint(0x20BB7)
        // "?"
        String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
        // true
        上面代碼中,如果String.fromCodePoint方法有多個(gè)參數(shù),則它們會(huì)被合并成一個(gè)字符串返回。
        注意,fromCodePoint方法定義在String對(duì)象上,而codePointAt方法定義在字符串的實(shí)例對(duì)象上。

        String.raw()

        ES6 還為原生的 String 對(duì)象,提供了一個(gè)raw()方法。該方法返回一個(gè)斜杠都被轉(zhuǎn)義(即斜杠前面再加一個(gè)斜杠)的字符串,往往用于模板字符串的處理方法。
        String.raw`Hi\n${2+3}!`
        // 實(shí)際返回 "Hi\\n5!",顯示的是轉(zhuǎn)義后的結(jié)果 "Hi\n5!"

        String.raw`Hi\u000A!`;
        // 實(shí)際返回 "Hi\\u000A!",顯示的是轉(zhuǎn)義后的結(jié)果 "Hi\u000A!"
        如果原字符串的斜杠已經(jīng)轉(zhuǎn)義,那么String.raw()會(huì)進(jìn)行再次轉(zhuǎn)義。
        String.raw`Hi\\n`
        // 返回 "Hi\\\\n"

        String.raw`Hi\\n` === "Hi\\\\n" // true
        String.raw()方法可以作為處理模板字符串的基本方法,它會(huì)將所有變量替換,而且對(duì)斜杠進(jìn)行轉(zhuǎn)義,方便下一步作為字符串來使用。
        String.raw()本質(zhì)上是一個(gè)正常的函數(shù),只是專用于模板字符串的標(biāo)簽函數(shù)。如果寫成正常函數(shù)的形式,它的第一個(gè)參數(shù),應(yīng)該是一個(gè)具有raw屬性的對(duì)象,且raw屬性的值應(yīng)該是一個(gè)數(shù)組,對(duì)應(yīng)模板字符串解析后的值。
        // `foo${1 + 2}bar`
        // 等同于
        String.raw({ raw: ['foo', 'bar'] }, 1 + 2) // "foo3bar"
        上面代碼中,String.raw()方法的第一個(gè)參數(shù)是一個(gè)對(duì)象,它的raw屬性等同于原始的模板字符串解析后得到的數(shù)組。
        作為函數(shù),String.raw()的代碼實(shí)現(xiàn)基本如下。
        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;
        }

        實(shí)例方法:codePointAt()

        JavaScript 內(nèi)部,字符以 UTF-16 的格式儲(chǔ)存,每個(gè)字符固定為2個(gè)字節(jié)。對(duì)于那些需要4個(gè)字節(jié)儲(chǔ)存的字符(Unicode 碼點(diǎn)大于0xFFFF的字符),JavaScript 會(huì)認(rèn)為它們是兩個(gè)字符。
        var s = "?";

        s.length // 2
        s.charAt(0) // ''
        s.charAt(1) // ''
        s.charCodeAt(0) // 55362
        s.charCodeAt(1) // 57271
        上面代碼中,漢字“?”(注意,這個(gè)字不是“吉祥”的“吉”)的碼點(diǎn)是0x20BB7,UTF-16 編碼為0xD842 0xDFB7(十進(jìn)制為55362 57271),需要4個(gè)字節(jié)儲(chǔ)存。對(duì)于這種4個(gè)字節(jié)的字符,JavaScript 不能正確處理,字符串長度會(huì)誤判為2,而且charAt()方法無法讀取整個(gè)字符,charCodeAt()方法只能分別返回前兩個(gè)字節(jié)和后兩個(gè)字節(jié)的值。
        ES6 提供了codePointAt()方法,能夠正確處理 4 個(gè)字節(jié)儲(chǔ)存的字符,返回一個(gè)字符的碼點(diǎn)。
        let s = '?a';

        s.codePointAt(0) // 134071
        s.codePointAt(1) // 57271

        s.codePointAt(2) // 97
        codePointAt()方法的參數(shù),是字符在字符串中的位置(從 0 開始)。上面代碼中,JavaScript 將“?a”視為三個(gè)字符,codePointAt 方法在第一個(gè)字符上,正確地識(shí)別了“?”,返回了它的十進(jìn)制碼點(diǎn) 134071(即十六進(jìn)制的20BB7)。在第二個(gè)字符(即“?”的后兩個(gè)字節(jié))和第三個(gè)字符“a”上,codePointAt()方法的結(jié)果與charCodeAt()方法相同。
        總之,codePointAt()方法會(huì)正確返回 32 位的 UTF-16 字符的碼點(diǎn)。對(duì)于那些兩個(gè)字節(jié)儲(chǔ)存的常規(guī)字符,它的返回結(jié)果與charCodeAt()方法相同。
        codePointAt()方法返回的是碼點(diǎn)的十進(jìn)制值,如果想要十六進(jìn)制的值,可以使用toString()方法轉(zhuǎn)換一下。
        let s = '?a';

        s.codePointAt(0).toString(16) // "20bb7"
        s.codePointAt(2).toString(16) // "61"
        你可能注意到了,codePointAt()方法的參數(shù),仍然是不正確的。比如,上面代碼中,字符a在字符串s的正確位置序號(hào)應(yīng)該是 1,但是必須向codePointAt()方法傳入 2。解決這個(gè)問題的一個(gè)辦法是使用for...of循環(huán),因?yàn)樗鼤?huì)正確識(shí)別 32 位的 UTF-16 字符。
        let s = '?a';
        for (let ch of s) {
        console.log(ch.codePointAt(0).toString(16));
        }
        // 20bb7
        // 61
        另一種方法也可以,使用擴(kuò)展運(yùn)算符(...)進(jìn)行展開運(yùn)算。
        let arr = [...'?a']; // arr.length === 2
        arr.forEach(
        ch => console.log(ch.codePointAt(0).toString(16))
        );
        // 20bb7
        // 61
        codePointAt()方法是測(cè)試一個(gè)字符由兩個(gè)字節(jié)還是由四個(gè)字節(jié)組成的最簡(jiǎn)單方法。
        function is32Bit(c) {
        return c.codePointAt(0) > 0xFFFF;
        }

        is32Bit("?") // true
        is32Bit("a") // false

        實(shí)例方法:normalize()

        許多歐洲語言有語調(diào)符號(hào)和重音符號(hào)。為了表示它們,Unicode 提供了兩種方法。一種是直接提供帶重音符號(hào)的字符,比如ǒ(\u01D1)。另一種是提供合成符號(hào)(combining character),即原字符與重音符號(hào)的合成,兩個(gè)字符合成一個(gè)字符,比如O(\u004F)和ˇ(\u030C)合成ǒ(\u004F\u030C)。
        這兩種表示方法,在視覺和語義上都等價(jià),但是 JavaScript 不能識(shí)別。
        '\u01D1'==='\u004F\u030C' //false

        '\u01D1'.length // 1
        '\u004F\u030C'.length // 2
        上面代碼表示,JavaScript 將合成字符視為兩個(gè)字符,導(dǎo)致兩種表示方法不相等。
        ES6 提供字符串實(shí)例的normalize()方法,用來將字符的不同表示方法統(tǒng)一為同樣的形式,這稱為 Unicode 正規(guī)化。
        '\u01D1'.normalize() === '\u004F\u030C'.normalize()
        // true
        normalize方法可以接受一個(gè)參數(shù)來指定normalize的方式,參數(shù)的四個(gè)可選值如下。
        • NFC,默認(rèn)參數(shù),表示“標(biāo)準(zhǔn)等價(jià)合成”(Normalization Form Canonical Composition),返回多個(gè)簡(jiǎn)單字符的合成字符。所謂“標(biāo)準(zhǔn)等價(jià)”指的是視覺和語義上的等價(jià)。

        • NFD,表示“標(biāo)準(zhǔn)等價(jià)分解”(Normalization Form Canonical Decomposition),即在標(biāo)準(zhǔn)等價(jià)的前提下,返回合成字符分解的多個(gè)簡(jiǎn)單字符。

        • NFKC,表示“兼容等價(jià)合成”(Normalization Form Compatibility Composition),返回合成字符。所謂“兼容等價(jià)”指的是語義上存在等價(jià),但視覺上不等價(jià),比如“囍”和“喜喜”。(這只是用來舉例,normalize方法不能識(shí)別中文。)

        • NFKD,表示“兼容等價(jià)分解”(Normalization Form Compatibility Decomposition),即在兼容等價(jià)的前提下,返回合成字符分解的多個(gè)簡(jiǎn)單字符。

        '\u004F\u030C'.normalize('NFC').length // 1
        '\u004F\u030C'.normalize('NFD').length // 2
        上面代碼表示,NFC參數(shù)返回字符的合成形式,NFD參數(shù)返回字符的分解形式。
        不過,normalize方法目前不能識(shí)別三個(gè)或三個(gè)以上字符的合成。這種情況下,還是只能使用正則表達(dá)式,通過 Unicode 編號(hào)區(qū)間判斷。

        實(shí)例方法:includes(), startsWith(), endsWith()

        傳統(tǒng)上,JavaScript 只有indexOf方法,可以用來確定一個(gè)字符串是否包含在另一個(gè)字符串中。ES6 又提供了三種新方法。
        • includes():返回布爾值,表示是否找到了參數(shù)字符串。

        • startsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的頭部。

        • endsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的尾部。

        let s = 'Hello world!';

        s.startsWith('Hello') // true
        s.endsWith('!') // true
        s.includes('o') // true
        這三個(gè)方法都支持第二個(gè)參數(shù),表示開始搜索的位置。
        let s = 'Hello world!';

        s.startsWith('world', 6) // true
        s.endsWith('Hello', 5) // true
        s.includes('Hello', 6) // false
        上面代碼表示,使用第二個(gè)參數(shù)n時(shí),endsWith的行為與其他兩個(gè)方法有所不同。它針對(duì)前n個(gè)字符,而其他兩個(gè)方法針對(duì)從第n個(gè)位置直到字符串結(jié)束。

        實(shí)例方法:repeat()

        repeat方法返回一個(gè)新字符串,表示將原字符串重復(fù)n次。
        'x'.repeat(3) // "xxx"
        'hello'.repeat(2) // "hellohello"
        'na'.repeat(0) // ""
        參數(shù)如果是小數(shù),會(huì)被取整。
        'na'.repeat(2.9) // "nana"
        如果repeat的參數(shù)是負(fù)數(shù)或者Infinity,會(huì)報(bào)錯(cuò)。
        'na'.repeat(Infinity)
        // RangeError
        'na'.repeat(-1)
        // RangeError
        但是,如果參數(shù)是 0 到-1 之間的小數(shù),則等同于 0,這是因?yàn)闀?huì)先進(jìn)行取整運(yùn)算。0 到-1 之間的小數(shù),取整以后等于-0,repeat視同為 0。
        'na'.repeat(-0.9) // ""
        參數(shù)NaN等同于 0。
        'na'.repeat(NaN) // ""
        如果repeat的參數(shù)是字符串,則會(huì)先轉(zhuǎn)換成數(shù)字。
        'na'.repeat('na') // ""
        'na'.repeat('3') // "nanana"

        實(shí)例方法:padStart(),padEnd()

        ES2017 引入了字符串補(bǔ)全長度的功能。如果某個(gè)字符串不夠指定長度,會(huì)在頭部或尾部補(bǔ)全。padStart()用于頭部補(bǔ)全,padEnd()用于尾部補(bǔ)全。
        'x'.padStart(5, 'ab') // 'ababx'
        'x'.padStart(4, 'ab') // 'abax'

        'x'.padEnd(5, 'ab') // 'xabab'
        'x'.padEnd(4, 'ab') // 'xaba'
        上面代碼中,padStart()和padEnd()一共接受兩個(gè)參數(shù),第一個(gè)參數(shù)是字符串補(bǔ)全生效的最大長度,第二個(gè)參數(shù)是用來補(bǔ)全的字符串。
        如果原字符串的長度,等于或大于最大長度,則字符串補(bǔ)全不生效,返回原字符串。
        'xxx'.padStart(2, 'ab') // 'xxx'
        'xxx'.padEnd(2, 'ab') // 'xxx'
        如果用來補(bǔ)全的字符串與原字符串,兩者的長度之和超過了最大長度,則會(huì)截去超出位數(shù)的補(bǔ)全字符串。
        'abc'.padStart(10, '0123456789')
        // '0123456abc'
        如果省略第二個(gè)參數(shù),默認(rèn)使用空格補(bǔ)全長度。
        'x'.padStart(4) // ' x'
        'x'.padEnd(4) // 'x '
        padStart()的常見用途是為數(shù)值補(bǔ)全指定位數(shù)。下面代碼生成 10 位的數(shù)值字符串。
        '1'.padStart(10, '0') // "0000000001"
        '12'.padStart(10, '0') // "0000000012"
        '123456'.padStart(10, '0') // "0000123456"
        另一個(gè)用途是提示字符串格式。
        '12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
        '09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"

        實(shí)例方法:trimStart(),trimEnd()

        ES2019?對(duì)字符串實(shí)例新增了trimStart()和trimEnd()這兩個(gè)方法。它們的行為與trim()一致,trimStart()消除字符串頭部的空格,trimEnd()消除尾部的空格。它們返回的都是新字符串,不會(huì)修改原始字符串。
        const s = ' abc ';

        s.trim() // "abc"
        s.trimStart() // "abc "
        s.trimEnd() // " abc"
        上面代碼中,trimStart()只消除頭部的空格,保留尾部的空格。trimEnd()也是類似行為。
        除了空格鍵,這兩個(gè)方法對(duì)字符串頭部(或尾部)的 tab 鍵、換行符等不可見的空白符號(hào)也有效。
        瀏覽器還部署了額外的兩個(gè)方法,trimLeft()是trimStart()的別名,trimRight()是trimEnd()的別名。

        實(shí)例方法:matchAll()

        matchAll()方法返回一個(gè)正則表達(dá)式在當(dāng)前字符串的所有匹配,詳見《正則的擴(kuò)展》的一章。
        本文完~

        瀏覽 41
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. caobimaopian | 貂蝉艳史在线观看 | 精品无码成人免费看视频 | 天天插天天操天天日 | 航空美女一级毛片 |