源自:https://es6.ruanyifeng.com/
第三章
字符的 Unicode 表示法
ES6 加強了對 Unicode 的支持,允許采用\uxxxx
形式表示一個字符和媳,其中xxxx
表示字符的 Unicode 碼點穿铆。
"\u0061"
// "a"
ES6 只要將碼點放入大括號掺逼,就能正確解讀超過0xFFFF
數(shù)值的字符
"\u{20BB7}"
// "??"
let hello = 123;
hell\u{6F} // 123
'\u{1F680}' === '\uD83D\uDE80'
// true
字符串的遍歷器接口
ES6 為字符串添加了遍歷器接口(詳見《Iterator》一章)缺菌,使得字符串可以被for...of
循環(huán)遍歷。
for (let codePoint of 'foo') {
console.log(codePoint)
}
// "f"
// "o"
// "o"
除了遍歷字符串洛退,這個遍歷器最大的優(yōu)點是可以識別大于0xFFFF
的碼點般甲,傳統(tǒng)的for
循環(huán)無法識別這樣的碼點。
直接輸入 U+2028 和 U+2029
JavaScript 字符串允許直接輸入字符俊马,以及輸入字符的轉(zhuǎn)義形式丁存。舉例來說,“中”的 Unicode 碼點是 U+4e2d柴我,你可以直接在字符串里面輸入這個漢字解寝,也可以輸入它的轉(zhuǎn)義形式\u4e2d
,兩者是等價的艘儒。
'中' === '\u4e2d' // true
但是聋伦,JavaScript 規(guī)定有5個字符,不能在字符串里面直接使用界睁,只能使用轉(zhuǎn)義形式觉增。
- U+005C:反斜杠(reverse solidus)
- U+000D:回車(carriage return)
- U+2028:行分隔符(line separator)
- U+2029:段分隔符(paragraph separator)
- U+000A:換行符(line feed)
ES2019允許 JavaScript 字符串直接輸入 U+2028(行分隔符)和 U+2029(段分隔符)
舉例來說,字符串里面不能直接包含反斜杠翻斟,一定要轉(zhuǎn)義寫成\\
或者\u005c
JSON.stringify() 的改造
UTF-8 標準規(guī)定逾礁,0xD800
到0xDFFF
之間的碼點,不能單獨使用,必須配對使用。比如碍脏,\uD834\uDF06
是兩個碼點惕它,但是必須放在一起配對使用,代表字符??
。這是為了表示碼點大于0xFFFF
的字符的一種變通方法。單獨使用\uD834
和\uDFO6
這兩個碼點是不合法的,或者顛倒順序也不行焰枢,因為\uDF06\uD834
并沒有對應(yīng)的字符。
JSON.stringify()
的問題在于舌剂,它可能返回0xD800
到0xDFFF
之間的單個碼點济锄。
為了確保返回的是合法的 UTF-8 字符,ES2019 改變了JSON.stringify()
的行為霍转。如果遇到0xD800
到0xDFFF
之間的單個碼點荐绝,或者不存在的配對形式,它會返回轉(zhuǎn)義字符串避消,留給應(yīng)用自己決定下一步的處理低滩。
JSON.stringify('\u{D834}') // ""\\uD834""
JSON.stringify('\uDF06\uD834') // ""\\udf06\\ud834""
模板字符串
模板字符串(template string)是增強版的字符串召夹,用反引號(`)標識。它可以當作普通字符串使用恕沫,也可以用來定義多行字符串监憎,或者在字符串中嵌入變量。
模板字符串中嵌入變量婶溯,需要將變量名寫在${}
之中鲸阔。模板字符串之中還能調(diào)用函數(shù)。
標簽?zāi)0?/h2>
模板字符串的功能迄委,不僅僅是上面這些褐筛。它可以緊跟在一個函數(shù)名后面,該函數(shù)將被調(diào)用來處理這個模板字符串叙身。這被稱為“標簽?zāi)0濉惫δ埽╰agged template)死讹。
alert`hello`
// 等同于
alert(['hello'])
標簽?zāi)0迤鋵嵅皇悄0澹呛瘮?shù)調(diào)用的一種特殊形式曲梗。“標簽”指的就是函數(shù)妓忍,緊跟在后面的模板字符串就是它的參數(shù)虏两。
但是,如果模板字符里面有變量世剖,就不是簡單的調(diào)用了定罢,而是會將模板字符串先處理成多個參數(shù),再調(diào)用函數(shù)旁瘫。
模板字符串的限制
前面提到標簽?zāi)0謇锩孀尜欤梢詢?nèi)嵌其他語言。但是酬凳,模板字符串默認會將字符串轉(zhuǎn)義惠况,導(dǎo)致無法嵌入其他語言。
第四章
String.fromCodePoint()
ES5 提供String.fromCharCode()
方法宁仔,用于從 Unicode 碼點返回對應(yīng)字符稠屠,但是這個方法不能識別碼點大于0xFFFF
的字符。
String.fromCharCode(0x20BB7)
// "?"
上面代碼中翎苫,String.fromCharCode()
不能識別大于0xFFFF
的碼點权埠,所以0x20BB7
就發(fā)生了溢出,最高位2
被舍棄了煎谍,最后返回碼點U+0BB7
對應(yīng)的字符攘蔽,而不是碼點U+20BB7
對應(yīng)的字符。
ES6 提供了String.fromCodePoint()
方法呐粘,可以識別大于0xFFFF
的字符满俗,彌補了String.fromCharCode()
方法的不足转捕。在作用上,正好與下面的codePointAt()
方法相反漫雷。
String.fromCodePoint(0x20BB7)
// "??"
String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
// true
上面代碼中瓜富,如果String.fromCodePoint
方法有多個參數(shù),則它們會被合并成一個字符串返回降盹。
注意与柑,fromCodePoint
方法定義在String
對象上,而codePointAt
方法定義在字符串的實例對象上蓄坏。
String.raw()
ES6 還為原生的 String 對象价捧,提供了一個raw()
方法。該方法返回一個斜杠都被轉(zhuǎn)義(即斜杠前面再加一個斜杠)的字符串涡戳,往往用于模板字符串的處理方法结蟋。
String.raw`Hi\n${2+3}!`
// 實際返回 "Hi\\n5!",顯示的是轉(zhuǎn)義后的結(jié)果 "Hi\n5!"
String.raw`Hi\u000A!`;
// 實際返回 "Hi\\u000A!"渔彰,顯示的是轉(zhuǎn)義后的結(jié)果 "Hi\u000A!"
如果原字符串的斜杠已經(jīng)轉(zhuǎn)義嵌屎,那么String.raw()
會進行再次轉(zhuǎn)義。
String.raw`Hi\\n`
// 返回 "Hi\\\\n"
String.raw`Hi\\n` === "Hi\\\\n" // true
String.raw()
方法可以作為處理模板字符串的基本方法宝惰,它會將所有變量替換,而且對斜杠進行轉(zhuǎn)義再沧,方便下一步作為字符串來使用尼夺。
String.raw()
本質(zhì)上是一個正常的函數(shù),只是專用于模板字符串的標簽函數(shù)炒瘸。如果寫成正常函數(shù)的形式淤堵,它的第一個參數(shù),應(yīng)該是一個具有raw
屬性的對象顷扩,且raw
屬性的值應(yīng)該是一個數(shù)組拐邪,對應(yīng)模板字符串解析后的值。
實例
ES6 提供了codePointAt()
方法隘截,能夠正確處理 4 個字節(jié)儲存的字符庙睡,返回一個字符的碼點。
let s = '??a';
s.codePointAt(0) // 134071
s.codePointAt(1) // 57271
s.codePointAt(2) // 97
codePointAt()
方法的參數(shù)技俐,是字符在字符串中的位置(從 0 開始)乘陪。上面代碼中,JavaScript 將“??a”視為三個字符雕擂,codePointAt 方法在第一個字符上啡邑,正確地識別了“??”,返回了它的十進制碼點 134071(即十六進制的20BB7
)井赌。在第二個字符(即“??”的后兩個字節(jié))和第三個字符“a”上谤逼,codePointAt()
方法的結(jié)果與charCodeAt()
方法相同贵扰。
總之,codePointAt()
方法會正確返回 32 位的 UTF-16 字符的碼點流部。對于那些兩個字節(jié)儲存的常規(guī)字符戚绕,它的返回結(jié)果與charCodeAt()
方法相同。
ES6 提供字符串實例的normalize()
方法枝冀,用來將字符的不同表示方法統(tǒng)一為同樣的形式舞丛,這稱為 Unicode 正規(guī)化。
'\u01D1'.normalize() === '\u004F\u030C'.normalize()
// true
normalize
方法可以接受一個參數(shù)來指定normalize
的方式果漾,參數(shù)的四個可選值如下球切。
-
NFC
,默認參數(shù)绒障,表示“標準等價合成”(Normalization Form Canonical Composition)吨凑,返回多個簡單字符的合成字符。所謂“標準等價”指的是視覺和語義上的等價户辱。 -
NFD
鸵钝,表示“標準等價分解”(Normalization Form Canonical Decomposition),即在標準等價的前提下庐镐,返回合成字符分解的多個簡單字符恩商。 -
NFKC
,表示“兼容等價合成”(Normalization Form Compatibility Composition)焚鹊,返回合成字符。所謂“兼容等價”指的是語義上存在等價韧献,但視覺上不等價末患,比如“囍”和“喜喜”。(這只是用來舉例锤窑,normalize
方法不能識別中文璧针。) -
NFKD
,表示“兼容等價分解”(Normalization Form Compatibility Decomposition)渊啰,即在兼容等價的前提下探橱,返回合成字符分解的多個簡單字符。
ES6 提供了三種新方法绘证。
- includes():返回布爾值隧膏,表示是否找到了參數(shù)字符串。
- startsWith():返回布爾值嚷那,表示參數(shù)字符串是否在原字符串的頭部胞枕。
- endsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的尾部魏宽。
repeat
方法返回一個新字符串腐泻,表示將原字符串重復(fù)n
次决乎。
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
參數(shù)如果是小數(shù),會被取整派桩。
'na'.repeat(2.9) // "nana"
如果repeat
的參數(shù)是負數(shù)或者Infinity
构诚,會報錯。
ES2017 引入了字符串補全長度的功能铆惑。如果某個字符串不夠指定長度范嘱,會在頭部或尾部補全。padStart()
用于頭部補全鸭津,padEnd()
用于尾部補全彤侍。
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
上面代碼中,padStart()
和padEnd()
一共接受兩個參數(shù)逆趋,第一個參數(shù)是字符串補全生效的最大長度盏阶,第二個參數(shù)是用來補全的字符串。
如果原字符串的長度闻书,等于或大于最大長度名斟,則字符串補全不生效,返回原字符串魄眉。
ES2019 對字符串實例新增了trimStart()
和trimEnd()
這兩個方法砰盐。它們的行為與trim()
一致,trimStart()
消除字符串頭部的空格坑律,trimEnd()
消除尾部的空格岩梳。它們返回的都是新字符串,不會修改原始字符串晃择。
const s = ' abc ';
s.trim() // "abc"
s.trimStart() // "abc "
s.trimEnd() // " abc"
上面代碼中冀值,trimStart()
只消除頭部的空格,保留尾部的空格宫屠。trimEnd()
也是類似行為列疗。
除了空格鍵,這兩個方法對字符串頭部(或尾部)的 tab 鍵浪蹂、換行符等不可見的空白符號也有效抵栈。
matchAll()
方法返回一個正則表達式在當前字符串的所有匹配
學(xué)習(xí)的文章:https://es6.ruanyifeng.com/