25

是否可以在 Javascript 中检测字符串是否包含多字节字符?如果是这样,是否可以分辨出哪些?

我遇到的问题是这个(如果 Unicode 字符不适合您,我们深表歉意)

s = "";

alert(s.length);    // '2'
alert(s.charAt(0)); // '��'
alert(s.charAt(1)); // '��'

在这里编辑一下(我希望) 据我所知,Javascript中的所有字符串都表示为一系列UTF-16代码点,这意味着常规字符实际上占用了2个字节(16位),所以我在标题中使用“多字节”有点离开。有些字符不属于基本多语言平面 (BMP),例如上面示例中的字符串,因此它们占用两个代码点(32 位)。这就是我要问的问题。我也没有编辑原始标题,因为对于不太了解这些东西的人(因此会搜索有关它的信息),“多字节”是有意义的。

4

1 回答 1

34

JavaScript 字符串是 UCS-2 编码的,但可以使用两个 16 位数字(UTF-16代理对U+0000)表示基本多语言窗格( -U+D7FFU+E000- )之外的 Unicode 代码点,其中第一个数字必须在-范围内。U+FFFFU+D800U+DFFF

基于此,很容易检测字符串是否包含位于基本多语言平面之外的任何字符(这就是我认为您要问的:您希望能够识别字符串是否包含位于范围之外的任何字符JavaScript 表示为单个字符的代码点):

function containsSurrogatePair(str) {
    return /[\uD800-\uDFFF]/.test(str);
}

alert( containsSurrogatePair("foo") ); // false
alert( containsSurrogatePair("f") ); // true

精确计算字符串中包含哪些代码点有点困难,并且需要 UTF-16 解码器。以下将字符串转换为 Unicode 代码点数组:

var getStringCodePoints = (function() {
    function surrogatePairToCodePoint(charCode1, charCode2) {
        return ((charCode1 & 0x3FF) << 10) + (charCode2 & 0x3FF) + 0x10000;
    }

    // Read string in character by character and create an array of code points
    return function(str) {
        var codePoints = [], i = 0, charCode;
        while (i < str.length) {
            charCode = str.charCodeAt(i);
            if ((charCode & 0xF800) == 0xD800) {
                codePoints.push(surrogatePairToCodePoint(charCode, str.charCodeAt(++i)));
            } else {
                codePoints.push(charCode);
            }
            ++i;
        }
        return codePoints;
    }
})();

alert( getStringCodePoints("f").join(",") ); // 102,119558
于 2011-02-03T10:36:31.870 回答