ES6標準入門 第四章:字符串的擴展
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標準入門 第四章:字符串的擴展