比较 unicode 字符时,Javascript 字符串比较失败

Posted

技术标签:

【中文标题】比较 unicode 字符时,Javascript 字符串比较失败【英文标题】:Javascript string comparison fails when comparing unicode characters 【发布时间】:2012-06-04 01:32:14 【问题描述】:

我想比较 javascript 中两个相同的字符串,但相等运算符 == 返回 false。一个字符串包含一个特殊字符(例如丹麦语å)。

JavaScript 代码:

var filenameFromJS = "Designhåndbog.pdf";
var filenameFromServer = "Designhåndbog.pdf";

print(filenameFromJS == filenameFromServer); // This prints false why?

解决方案 对我有用的是 slevthan 指出的 unicode 规范化。

我分叉了我原来的 jsfiddle 以使用 slevthan 建议的规范化库制作一个版本。链接:http://jsfiddle.net/GWZ8j/1/.

【问题讨论】:

查看这篇关于=====***.com/questions/359494/…的文章 @Steve 当两个操作数属于同一类型时,使用松散比较还是严格比较都没关系。 这也很有用:joelonsoftware.com/2003/10/08/…(每个开发者都需要了解的关于 unicode 和字符集的知识) 【参考方案1】:

与这里的其他人所说的不同,这与编码无关。相反,您的两个字符串使用不同的代码点来呈现相同的视觉字符。

要正确解决此问题,您需要在比较两个字符串之前对它们执行 Unicode 规范化。不幸的是,JavaScript 没有内置此功能。这是一个可以为您执行规范化的 JavaScript 库:https://github.com/walling/unorm

【讨论】:

哦,我希望不要得到这个答案 :-) 我只是错过了显而易见的事情,并且不需要图书馆来完成这个简单的任务。谢谢你的回答,我试试看。 你说得对,我错过了CC 8AU+30A COMBINING RING ABOVE的UTF-8编码序列,前面是a。另一个字符串有C3 A5,它用UTF-8 编码U+00E5 LATIN SMALL LETTER A WITH RING ABOVE。 IIRC,Mac OS 更喜欢组合字符,而其他操作系统更喜欢单字形形式。不过,应该可以让服务器转换任何一个,因此不需要大型客户端库。 PointedEars,这不一定是可能的或理想的。例如,您可能不想为了执行字符串比较而进行服务器往返,或者您可能在服务器上使用 JavaScript。 @Tougher,有一个提议将 Unicode 规范化添加到 JavaScript 的未来版本中。见strawman:unicode_normalization。【参考方案2】:

JavaScript 相等运算符== 在以下情况下会出现故障。在所有情况下,它都是程序员错误。不是 JavaScript 中的错误。

    这两个字符串不包含相同数量和序列的字符。

    在一个字符串之前、之中或之后有空格或换行符。对两者都使用 trim() 运算符并仔细查看两个字符串。

    令人惊讶的类型转换。程序员正在比较不兼容的数据类型。

    有些 unicode 字符看起来与其他 unicode 字符相同,但实际上是不同的 unicode 字符。

【讨论】:

+1,因为这个答案比接受的答案更丰富,并且不包含 nodeJS 或 jQuery 的内容。 在这种情况下,4号是罪魁祸首 不同的 unicode 规范化不是关于不同的字符,而是意味着使用不同的 unicode 代码点序列来指代同一个字符。【参考方案3】:

UTF-8 是一个复杂的东西。字符集有两个不同的字符代码,例如 á、é 等。正如您在 URL 编码版本中看到的那样,两个版本的字符的 HEX 字节不同。

有关更多信息,请参阅this 答案。

【讨论】:

JFTR:Unicode 不是 UTF-8。 Unicode 是一个字符集和几种编码的标准; UTF-8 就是其中一种编码。 现在你说 UTF-8 是一个字符集。它不是。我也相当肯定您的前提是错误的:UTF-8 代码序列可能不以 0xCC 开头。 你说得对,我应该把它称为“编码”,就像它出现的那样 (w3.org/TR/html4/charset.html)。 HTML 代码是 <meta charset=UTF-8> (HTML5) 或 <meta http-equiv=Content-Type content='text/html; charset=UTF-8'>,但是这有点误导。 是的,我想我们将不得不在很长一段时间内忍受早期 Internet 草案中的错误(我说的是 RFC 822 和这里的朋友)。 我对 0xCC 的看法是错误的。 Richard Ishida's excellent Unicode tools 证明了这一点。【参考方案4】:

我遇到了同样的问题。

添加

<meta charset="UTF-8">

到 HTML 文件修复了问题。

在我的例子中,模板引擎将一个 json 字符串烘焙到 HTML 文件中。这个字符串是 unicode 格式的。

虽然模板也是一个 unicode 文件,但 JS 引擎将我写入模板的字符串视为 latin-1 编码字符串,直到我添加了元标记。

我正在将输入的字符串与其中一个 JSON 对象项 (location.title == "Mühle") 进行比较

【讨论】:

【参考方案5】:

让浏览器为您规范化 unicode。这种方法对我有用:

function normalizeUnicode(s) 
    let div = $('<div style="display: none"></div>').html(s).appendTo('body');
    let res = div.html();
    div.remove();
    return res;


normalizeUnicode(unicodeVal1) == normalizeUnicode(unicodeVal2)

【讨论】:

以上是关于比较 unicode 字符时,Javascript 字符串比较失败的主要内容,如果未能解决你的问题,请参考以下文章

javascript基础03

Javascript RegExp + 单词边界 + unicode 字符

将 Unicode 字符插入 JavaScript

javascript转到带有unicode字符的url

JavaScript:Unicode 空格字符

JavaScript浅析javaScript和HTML与unicode字符集的关系