技术实践

===比较JavaScript字符串是否安全

当字符来自基本多语言平面时,可以直接比较字符串 ,但是,如果字符串可以包含组合字符,那么使用 string.normalize ()函数将比

羊先生的头像
羊先生2020.10.11 · 5 分钟阅读 · 36 阅读
===比较JavaScript字符串是否安全封面
文章正文还需 5 分钟

为了更好的描述观点,首先让我们来比较2个正常的字符串str1和str2:

js 复制代码
const str1 = 'Hello!';
const str2 = 'Hello!';

str1 === str2; // => true

因为str1和str2具有相同的字符,所以这些字符串相等

总是看起来两个相同的字符串相等吗?让我们尝试另一个示例:

js 复制代码
const str1 = 'café';
const str2 = 'café';

str1 === str2; // => false

如果有小伙伴不相信,自己打开浏览器测试就知道

虽然str1和str2看起来是一样的,比较str1 === str2计算结果为false。那怎么可能

让我们详细介绍如何正确比较JavaScript中的字符串。在开始之前,需要熟悉javascript是如何去完成比较一个字符串的

一个字母是什么

来看看下面的字符串

js 复制代码
const str1 = 'café';

可以很容易地看到它有4个字母: 小写的 c,小写的 a,小写的 f,小写的 e

下面是一个关于字符的定义:

"Grapheme is a minimally distinctive unit of writing in the context of a particular writing system."
在特定的书写系统中,字符是一个最小的独特的书写单位

什么是组合字符

组合字符包括重音符号发音符号希伯来语点阿拉伯语元音符号印度语母音符号

例如,é 是一个原子字素。使用小写字母 e (基本字符) ,并将它与锐角重音符 something (组合字符)结合起来呈现字符: e + something = é

js 复制代码
const e1 = 'e\u0301';

e1; // "é"

其中 u0301是组合字符 something 的 unicode 转义序列

所以,尽管 e1和 e2呈现的是相同的字形,但它们是不同的字符串值:

js 复制代码
const e1 = 'e\u0301';
const e2 = 'é';

e1 === e2; // => false

如何安全比较

首先,可以使用正则比较运算符 = = 、 = = 或效用函数 Object.is ()比较包含来自基本 Multilangual 平面的字符(包括 ASCII 字符)的字符串

js 复制代码
const str1 = 'Hello!';
const str2 = 'Hello!';

str1 === str2; // => true

Str1和 str2都包含 ASCII 字符,因此可以安全地使用比较运算符比较它们

其次,如果您处理基本多语言平面之上的字符,包括组合字符,那么使用 = = 、 = = 和 Object.is ()比较字符串是不安全的。另外需要做的是规范化比较的字符串。

js 复制代码
const str1 = 'café';
const str2 = 'cafe\u0301'; // same as 'café'

str1 === str2;                         // => false
str1.normalize() === str2.normalize(); // => true

简单地说,字符串规范化使规范等效字符串(‘ café’和‘ cafe u0301’等效,因为它们表示相同的字符串)具有唯一的表示形式(‘ café’和‘ cafe u0301’都规范化为唯一的‘ café’),使用normalize来序列化

总结

1、当字符来自基本多语言平面时,可以直接比较字符串
2、但是,如果字符串可以包含组合字符,那么使用 string.normalize ()函数将比较字符串规范化为相同的形式会更安全。然后对规范化字符串执行比较。

文章来自:dmitripavlutin
翻译:羊先生