1. 程式人生 > >ES6標準入門 第四章:字符串的擴展

ES6標準入門 第四章:字符串的擴展

固定 缺陷 長度 需要 允許 實例對象 poi turn har

1、字符串的Unicode 表示法

JavaScript 允許采用 \uxxxx 表示一個字符,其中 xxxx 表示字符的碼點

"\u0061"     // "a"

ES5中的缺陷:

以上表示法只限於 \u0000——\uFFFF 之間的字符。超出這個範圍的=字符,必須用兩個雙字節表示。

"\uD842\uDFB7"    //"??"

如果直接在\u 後面直接加上超過\uFFFF 的數值:

"\u20BB7"     // "  7"

如上代碼,JavaScript會理解成 “\u20BB+7” 。由於\u20BB 是一個不可打印字符, 所以顯示一個空格。

ES6的改進:

只要將碼點放入大括號,就能正確解讀改字符。

"\u{20BB7}"    // "??"

"\u{41}\u{42}\u{43}"     // "ABC"

let hello = 123;
hell\u{6F} // 123
‘\u{1F680}‘ === ‘\uD83D\uDE80‘ // true 此行代碼表示:大括號表示法 與 四字節的UTF-16編碼是等價的。

在JavaScript 中共有6種方法可以表示一個字符:

‘\z‘ === ‘z‘  // true
‘\172‘ === ‘z‘ // true
‘\x7A‘ === ‘z‘ // true
‘\u007A‘ === ‘z‘ // true
‘\u{7A}‘ === ‘z‘ // true


2、codePointAt()

JavaScript 內部,字符以UTF-16 的格式存儲,每個字符固定為2字節。 對於Unicode 碼點大於0xFFFF 的字符(需要4個字節存儲),js會認為它們是2 個字符。

ES5的缺陷:

var s = "??";

s.length // 2
s.charCodeAt(0) // 55362
s.charCodeAt(1) // 57271

上面的代碼中,?? 的碼點是0x20BB7,UTF-16 編碼為0xD842 0xDFB7(十進制為55362 57271),需要4個字節儲存。

對於這種四字節字符,JavaScript不能正確處理,字符串長度會被誤認為2;charCodeAt 方法只能分別返回前兩個字節的值 和 後兩個字節的值。

ES6 的改進:

提供了codePointAt方法,能夠正確處理4 字節字符,返回一個32位的UTF-16字符的碼點。(返回的碼點是十進制的)

let s = ‘??a‘;

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

參數為字符在字符串中的位置(從0開始); 對於兩個字節存儲的常規字符,它的返回結果與charCodeAt方法相同。

若要codePointAt方法返回的是十六進制的值,可以使用 toString方法轉換一下。

let s = ‘??a‘;

s.codePointAt(0).toString(16) // "20bb7"
s.codePointAt(2).toString(16) // "61"

以上代碼仍然存在問題:codePointAt方法的參數仍然是不正確的。【a在字符串的位置是1, 但是傳參卻是2】

解決方法: 使用for…of 循環,因為它可以正確識別32位的 UTF-16字符。

let s = ‘??a‘;
for (let i of s) {
   console.log( i.codePointAt(0).toString(16) );
}
// "20bb7"
// "61"

codePointAt 方法 是測試一個字符由 2個字節 還是 4個字節 組成的最簡單的方法。

function is32Bit( c ) {
   return c.codePiontAt(0) > 0xFFFF;
}
is32Bit("
??"); // true

is32Bit("a"); // true


3、String.fromCodePoint()

ES5 的缺陷:

String.fromCharCode 用於從碼點返回對應的字符,但是不能識別大於Unicode編碼 0xFFFF 的字符(32位的UTF-16字符)

String.fromCharCode(0x20BB7)
// "?"

上面代碼 0x20BB7發生溢出最高位兩位被舍棄,最後返回碼點U+0BB7對應的字符,而不是碼點U+20BB7對應的字符。

ES6的改進:

String.fromCodePoint 方法,可以識別大於0xFFFF 的碼點;作用上正好與 codePointAt 相反

String.fromCodePoint(0x20BB7)
// "??"
String.fromCodePoint(0x78, 0x1f680, 0x79) === ‘x\uD83D\uDE80y‘
// true

方法中有多個參數,則它們會被合並成一個字符串返回。

註意: fromCodePoint 方法定義在 String對象上, 而codePointAt 方法定義在字符串的實例對象上。

ES6標準入門 第四章:字符串的擴展