ES6加強(qiáng)了對Unicode的支持兴枯,并擴(kuò)展了字符串的 對象
1. 字符的Unicode表示法
js允許用\uxxxx
來表示一個字符,但只限于碼點(diǎn)在\u0000
~\uFFFF
之間矩欠,超出這個范圍的字符可用兩個雙字節(jié)表示财剖。
如果\u
后面加超過0xFFFF
的數(shù)值悠夯,js會理解成一個碼點(diǎn)和一個字符,比如\u20BB7
會理解成\u20BB+7
峰伙,打印出“7”
但是如果加了大括號,如\u{20BB7}
就能正確解讀字符
"\u{20BB7}"
// "??"
"\u{41}\u{42}\u{43}"
// "ABC"
let hello = 123;
hell\u{6F} // 123
'\u{1F680}' === '\uD83D\uDE80'
// true
2. codePointAt()
js內(nèi)部该默,字符以 UTF-16 的格式儲存瞳氓,每個字符固定為2
個字節(jié)。
背景:漢字“??”的碼點(diǎn)是0x20BB7
栓袖,UTF-16 編碼為0xD842 0xDFB7
匣摘,需要4
個字節(jié)儲存。對于這種4
個字節(jié)的字符裹刮,JavaScript 不能正確處理音榜,字符串長度會誤判為2
,而且charAt
方法無法讀取整個字符捧弃,charCodeAt
方法只能分別返回前兩個字節(jié)和后兩個字節(jié)的值赠叼。
結(jié)果:ES6提供了codePointAt方法,能正確處理四個字節(jié)存儲的字符违霞,返回一個字符的碼點(diǎn)(十進(jìn)制)
-
codePointAt方法:這個方法的參數(shù)是字符在字符串中的位置嘴办,如果一個漢字占了兩個字符,那么0代表漢字的前兩個字節(jié)买鸽,1代表漢字的后兩個字節(jié)
如果想要將這個函數(shù)返回的十進(jìn)制數(shù)轉(zhuǎn)換成十六進(jìn)制涧郊,可以使用toString方法
let s = '??a'; s.codePointAt(0).toString(16) // "20bb7" s.codePointAt(2).toString(16) // "61"
-
注意:codePointAt方法傳入的序號有時候是不正確的(比如上面代碼中a的序號應(yīng)該是1),為了解決這個問題眼五,可以使用
for...of
循環(huán)let s = '??a'; for (let ch of s) { console.log(ch.codePointAt(0).toString(16)); } // 20bb7 // 61
3. String.fromCodePoint()
ES5 提供String.fromCharCode
方法妆艘,用于從碼點(diǎn)返回對應(yīng)字符,但是這個方法不能識別 32 位的 UTF-16 字符(Unicode 編號大于0xFFFF
)看幼。
String.fromCharCode(0x20BB7)
// "?"
ES6提供了String.fromCodePoint
方法批旺,可以識別大于0xFFFF
的字符
- 注意:
String.fromCodePoint
方法定義在String對象上,但codePointAt
方法定義在字符串的實(shí)例對象上诵姜。
4. 字符串的遍歷器接口
ES6 為字符串添加了遍歷器接口朱沃,使得字符串可以被for...of
循環(huán)遍歷。
- 優(yōu)點(diǎn):
for...of
可以識別大于0xFFFF
的碼點(diǎn)茅诱,但for循環(huán)不行
5. normalize()
Unicode提供了兩種方法用來表示語調(diào)符號和重音符號逗物。一種是直接提供重音符號的字符,另一種是提供合成符號
JavaScript將合成字符當(dāng)成兩個字符瑟俭,所以雖然用兩種方法可以表示同一個字符翎卓,但實(shí)際上JavaScript是識別不了的
ES6提供normalize()
方法來解決上述問題
'\u01D1'.normalize() === '\u004F\u030C'.normalize()
// true
normalize
方法可以接受一個參數(shù)指定方式汽久,參數(shù)可選值如下:
NFC
刃麸,默認(rèn)參數(shù),表示“標(biāo)準(zhǔn)等價合成”棕洋,返回多個簡單字符的合成字符。所謂“標(biāo)準(zhǔn)等價”指的是視覺和語義上的等價逗扒。NFD
古戴,表示“標(biāo)準(zhǔn)等價分解”,即在標(biāo)準(zhǔn)等價的前提下矩肩,返回合成字符分解的多個簡單字符现恼。NFKC
,表示“兼容等價合成”黍檩,返回合成字符叉袍。所謂“兼容等價”指的是語義上存在等價,但視覺上不等價刽酱,比如“囍”和“喜喜”喳逛。NFKD
,表示“兼容等價分解”棵里,即在兼容等價的前提下润文,返回合成字符分解的多個簡單字符。
6. includes(),startsWith(),endsWith()
除了indexOf方法可以用來確定一個字符串是否包含在另一個字符串中殿怜,還有另外三種方法:
includes():返回布爾值转唉,表示是否找到了參數(shù)字符串。
startsWith():返回布爾值稳捆,表示參數(shù)字符串是否在原字符串的頭部赠法。
endsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的尾部乔夯。
這三個方法都支持第二個參數(shù)砖织,表示開始搜索的位置。但是endwith針對的是前n個字符末荐。
7. repeat()
這個方法返回一個新字符串侧纯,表示將原字符串重復(fù)n次。參數(shù)可能情況如下:
如果參數(shù)是小數(shù)甲脏,小數(shù)會被取整眶熬。
如果參數(shù)是負(fù)數(shù),會報錯
如果參數(shù)是零到負(fù)一之間的小數(shù)块请,等同于零
如果是NaN也等同于零
如果參數(shù)是字符串娜氏,會先轉(zhuǎn)換成數(shù)字
'x'.repeat(3) // "xxx"
'na'.repeat(2.9) // "nana"
'na'.repeat(NaN) // ""
'na'.repeat('na') // ""
8. padStart(),padEnd()
這兩個方法用于補(bǔ)全字符串墩新,padStart()
用于頭部補(bǔ)全贸弥,padEnd()
用于尾部補(bǔ)全。
這兩個方法一共接受兩個參數(shù)海渊,第一個參數(shù)是字符串補(bǔ)全生效的最大長度绵疲,第二個參數(shù)是用來補(bǔ)全的字符串哲鸳。
如果原字符串的長度,等于或大于最大長度盔憨,則字符串補(bǔ)全不生效徙菠,返回原字符串。
'xxx'.padStart(2, 'ab') // 'xxx'
'xxx'.padEnd(2, 'ab') // 'xxx'
如果用來補(bǔ)全的字符串與原字符串郁岩,兩者的長度之和超過了最大長度婿奔,則會截去超出位數(shù)的補(bǔ)全字符串。
'abc'.padStart(10, '0123456789')
// '0123456abc'
如果第二個參數(shù)省略驯用,默認(rèn)用空格補(bǔ)全長度
9. 模板字符串
模板字符串(template string)是增強(qiáng)版的字符串脸秽,用反引號(`)標(biāo)識儒老。它可以當(dāng)作普通字符串使用蝴乔,也可以用來定義多行字符串(所有空格和縮進(jìn)都會保留哎輸出中),或者在字符串中嵌入變量驮樊。
// 普通字符串
`In JavaScript '\n' is a line-feed.`
// 多行字符串
`In JavaScript this is
not legal.`
console.log(`string text line 1
string text line 2`);
// 字符串中嵌入變量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
如果在多行文本中消除換行薇正,可以使用trim消除
在${}中可以使用字符串、變量和表達(dá)式囚衔,也可以調(diào)用函數(shù)
模板字符串能嵌套挖腰,可以在模板字符串的變量之中,嵌入了另一個模板字符串练湿,如下:
const tmpl = addrs => `
${addrs.map(addr => `
`).join('')}
${addr.first}
${addr.last}
`;
const data = [
{ first: '', last: 'Bond' },
{ first: 'Lars', last: '' },
];
console.log(tmpl(data));
//
//
//
//
//
//
//
//
// BondLars
10. 標(biāo)簽?zāi)0?/h2>
標(biāo)簽?zāi)0?/strong>:模板字符串也可以緊跟在一個函數(shù)名后面猴仑,這個函數(shù)將被調(diào)用來處理這個模板字符串
alert`123`
// 等同于
alert(123)
如果模板字符里面有變量,會將模板字符串先處理成多個參數(shù)再調(diào)用函數(shù)肥哎。下面這個函數(shù)的第一個參數(shù)是一個數(shù)組辽俗,其他參數(shù)都是模板字符串被替換后的值
let a = 5;
let b = 10;
tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);
標(biāo)簽?zāi)0蹇梢杂脕磉^濾掉HTML字符串,防止用戶惡意輸入
11. String.raw()
這個方法用來充當(dāng)模板字符串的處理函數(shù),返回一個斜杠都被轉(zhuǎn)義的字符串篡诽,對應(yīng)于替換變量后的模板字符串崖飘。
這個方法也可以作為正常函數(shù)使用,它的第一個參數(shù)是一個具有raw
屬性的對象杈女,且raw
屬性的值應(yīng)該是一個數(shù)組朱浴。
String.raw({ raw: 'test' }, 0, 1, 2);
// 't0e1s2t'
// 等同于
String.raw({ raw: ['t','e','s','t'] }, 0, 1, 2);
12. 模板字符串的限制
模板字符串默認(rèn)會將字符串轉(zhuǎn)義,導(dǎo)致無法嵌入其他語言达椰,如下:
function latex(strings) {
// ...
}
let document = latex`
\newcommand{\fun}{\textbf{Fun!}} // 正常工作
\newcommand{\unicode}{\textbf{Unicode!}} // 報錯
\newcommand{\xerxes}{\textbf{King!}} // 報錯
Breve over the h goes \u{h}ere // 報錯
`
ES2018放松了對標(biāo)簽?zāi)0謇锩娴淖址D(zhuǎn)義限制翰蠢,遇到不合法字符就返回undefined,并且從raw屬性上面可以得到元字符串
但是啰劲,這種對字符串轉(zhuǎn)義的放松躏筏,只在標(biāo)簽?zāi)0?/strong>解析字符串時生效,不是標(biāo)簽?zāi)0宓膱龊铣释鳎廊粫箦e趁尼。