首页 > 解决方案 > Unicode 无法使用 JavaScript 正确显示

问题描述

convert.onclick =
  function() {
    for (var i = 0; i < before.value.length; i++) {
      after.value += "'" + before.value.charAt(i) + "', ";
    }
  }
<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>

这是一个简单的代码,当我操作它时,我得到以下结果。

问题

一些字母已成功转换。但是大多数 Unicode 字符都不能正常显示。我该如何解决这个问题?

标签: javascript

解决方案


您遇到的称为代理对。一些 unicode 字符由两个字节而不是一个字节组成,如果将它们分开,它们将不再正确显示。

如果您可以使用 ES6,则使用扩展运算符for..of语法迭代字符串实际上会考虑代理对,并且更容易为您提供正确的结果。其他答案显示了如何做到这一点。

如果你不能使用 ES6,MDN 有一个如何处理这些的charAt 例子。我将在下面使用此代码。

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>


推荐阅读