ECMASCRIPT 6中字串的新特性
本文將覆蓋在ECMAScript 6 (ES6)中,字串的新特性。
Unicode 碼位(code point)轉義
Unicode字元碼位的長度是21位[2]。而JavaScript的字串,是16位的,以UTF-16的方式編碼。因此,超出16位碼長的碼位範圍(the Basic Multilingual Pane, BMP, 基本多文種平面)則用兩個JavaScript字元表示。直到現在,如果想用數字指定這樣的碼位,需要兩個叫Unicode轉義符的東西。以下,則會以相應的碼位(0x1F680)打印出一個火箭。
console.log('\uD83D\uDE80');
在ECMAScript 6中,有一個新的Unicode轉義符,能讓你指定任意的碼位(不用再管是否是16位):
console.log('\u{1F680}');
字串的插值,多行及原始字元語法
模板字串 [3]提供了3個有意思的特性。
1. 模板字元中,支援字串插值:
let first = 'Jane';
let last = 'Doe';
console.log(`Hello ${first} ${last}!`);
// Hello Jane Doe!
2. 模板字串可以包含多行:
let multiLine = `
This is
a string
with multiple
lines`;
3. 模板字串可以是原始的:
若使用String.raw
\n
也不會被解釋成換行符:
let raw = String.raw`Not a newline: \n`;
console.log(raw === 'Not a newline: \\n'); // true
字串迭代那些事
字串是可迭代的 [4],這就意味著可以使用for-of
去迭代其中的字元:
for (let ch of 'abc') {
console.log(ch);
}
// Output:
// a
// b
// c
亦可用展開執行符(...) 將字串轉換成陣列:
let chars = [...'abc']; // ['a', 'b', 'c']
處理Unicode的碼位
字串迭代器,會以碼位邊界將字串進行劃分。這將導致迭代器的返回值,會是一個或兩個字元:
for (let ch of 'x\uD83D\uDE80y') {
console.log(ch.length);
}
// Output:
// 1
// 2
// 1
這將會為我提供一個快速而簡單的方法,去計算字串Unicode碼位的數量:
> [...'x\uD83D\uDE80y'].length
3
這同樣會在,不包含基本多文種平面(non-BMP)碼位的字串操作中提供方便。如:反轉字串:
let str = 'x\uD83D\uDE80y';
// ES5: \uD83D\uDE80 are (incorrectly) reversed
console.log(str.split('').reverse().join(''));
// 'y\uDE80\uD83Dx'
// ES6: order of \uD83D\uDE80 is preserved
console.log([...str].reverse().join(''));
// 'y\uD83D\uDE80x'
這是在firefox控制檯中,兩個反轉之後的結果:
碼位中數值
有一個新的方法 codePointAt()
將返回字串,給定索引的碼位數字值:
let str = 'x\uD83D\uDE80y';
console.log(str.codePointAt(0).toString(16)); // 78
console.log(str.codePointAt(1).toString(16)); // 1f680
console.log(str.codePointAt(3).toString(16)); // 79
該方法在與字串迭代操作結合時,也能很好的執行使用:
for (let ch of 'x\uD83D\uDE80y') {
console.log(ch.codePointAt(0).toString(16));
}
// Output:
// 78
// 1f680
// 79
與方法codePointAt()
相對的則是String.fromCodePoint()
:
> String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
true
包含與重要字串的方法
有三個方法,可以檢查一個字串是否存在於另一個字串:
> 'hello'.startsWith('hell')
true
> 'hello'.endsWith('ello')
true
> 'hello'.includes('ell')
true
每一個方法都有一個可選的,第二個引數。可以指定被搜尋字串的開始或結束位置:
> 'hello'.startsWith('ello', 1)
true
> 'hello'.endsWith('hell', 4)
true
> 'hello'.includes('ell', 1)
true
> 'hello'.includes('ell', 2)
false
方法repeat()
則用以重複某個字串:
> 'doo '.repeat(3)
'doo doo doo '
所有新方法
模板字串:
- String.raw(callSite, ...substitutions) : string
用於產生原始(raw)字串(反斜槓不會被轉義)。
Unicode和碼位:
String.fromCodePoint(...codePoints : number[]) : string
將數字值碼位轉換成字串。String.prototype.codePointAt(pos) : number
返回碼位開始位置的數字值(會包含一個或兩個JavaScript的字元)。String.prototype.normalize(form? : string) : string
不同的碼位組合,最後可能有一致的顯示。Unicode normalization可以將它們轉化成同樣的值,這會被叫做規範的表示方式(canonical representation)。這將有助於比較和查詢字串。在一般的文字之中,'NFC'是一種被推薦的形式。
查詢字串:
String.prototype.startsWith(searchString, position=0) : boolean
檢查一個字串是否以另一個字串(searchString)開始。位置(position)指定從哪開始執行檢查。String.prototype.endsWith(searchString, endPosition=searchString.length) : boolean
檢查一個字串是否以另一個字串(searchString)結尾。結束位置(endPosition)指定在哪執行結尾檢查。String.prototype.includes(searchString, position=0) : boolean
檢查一個字元字串是否包含另一個字串(searchString)。位置(position)指定從哪開始檢查。
重複字串:
- String.prototype.repeat(count) : string
返回給定字串N次。