1. 程式人生 > >ECMASCRIPT 6中字串的新特性

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

作為模板字串的字首,則模板字串可以是原始(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次。

參考