What you're running into are called surrogate pairs. Some unicode characters are composed of two bytes instead of one, and if you separate them, they no longer display correctly.
If you can use ES6, iterating a string with the spread operator or for..of syntax actually takes surrogate pairs into account and will give you correct results easier. Other answers show how to do this.
If you can't use ES6, MDN has an example of how to handle these with charAt here. I'll use this code below.
function getWholeChar(str, i) {
var code = str.charCodeAt(i);
if (Number.isNaN(code)) return '';
if (code < 0xD800 || code > 0xDFFF) return str.charAt(i);
if (0xD800 <= code && code <= 0xDBFF) {
if (str.length <= (i + 1)) throw 'High surrogate without following low surrogate';
var next = str.charCodeAt(i + 1);
if (0xDC00 > next || next > 0xDFFF) throw 'High surrogate without following low surrogate';
return str.charAt(i) + str.charAt(i + 1);
}
if (i === 0) throw 'Low surrogate without preceding high surrogate';
var prev = str.charCodeAt(i - 1);
if (0xD800 > prev || prev > 0xDBFF) throw 'Low surrogate without preceding high surrogate';
return false;
}
convert.onclick =
function() {
for (var i = 0, chr; i < before.value.length; i++) {
if(!(chr = getWholeChar(before.value, i))) continue;
after.value += "'" + chr + "', ";
}
}
<textarea id="before" type="text" name="input" style="width:100%;">*𝟡(𝟘)-_=+𝕢ℚ𝕨𝕎𝕖𝔼𝕣ℝ𝕥𝕋𝕪𝕐𝕦𝕌</textarea><br />
<textarea id="after" cols="50" rows="10" name="output" style="width:100%;"></textarea>
<button id="convert" name="convert" type="button">convert</button>
lengthof1?