views:

69

answers:

1

According to JavaScript: the Good Parts:

JavaScript was built at a time when Unicode was a 16-bit character set, so all characters in JavaScript are 16 bits wide.

This leads me to believe that JavaScript uses UCS-2 (not UTF-16!) and can only handle characters up to U+FFFF.

Further investigation confirms this:

> String.fromCharCode(0x20001);

The fromCharCode method seems to only use the lowest 16 bits when returning the Unicode character. Trying to get U+20001 (CJK unified ideograph 20001) instead returns U+0001.

Question: is it at all possible to handle post-BMP characters in JavaScript?

+1  A: 

Depends what you mean by ‘support’. You can certainly put non-UCS-2 characters in a JS string using surrogates, and browsers will display them if they can.

But, each item in a JS string is a separate UTF-16 code unit. There is no language-level support for handling full characters: all the standard String members (length, split, slice etc) all deal with code units not characters, so will quite happily split surrogate pairs or hold invalid surrogate sequences.

If you want surrogate-aware methods, I'm afraid you're going to have to start writing them yourself! For example:

String.prototype.getFullCharLength= function() {
    return this.length-this.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g).length+1;
};

String.fromFullCharCode= function() {
    var chars= [];
    for (var i= 0; i<arguments.length; i++) {
        var n= arguments[i];
        if (n<0x10000)
            chars.push(String.fromCharCode(n));
        else
            chars.push(String.fromCharCode(
                0xD800+((n-0x10000)&0x3FF),
                0xDC00+(((n-0x10000)>>10)&0x3FF)
            ));
    }
    return chars.join('');
};
bobince
Thank you very much. That's a great, detailed answer.
Delan Azabani