为什么 '❌'[0] === '❌' 而 '✔️'[0] !== '✔️'?

Why '❌'[0] === '❌' but '✔️'[0] !== '✔️'?

'❌'[0] === '❌' // true
'✔️'[0] === '✔️' // false
'✔️'[0] === '✔'  // true

我怀疑它与 unicode 相关,但想准确了解发生了什么以及如何正确比较这些字符。为什么 '✔️' 与 '❌' 的处理方式不同?

我在这个简单的字符计数中遇到了

'✔️❌✔️❌'.split('').filter(e => e === '❌').length // 2
'✔️❌✔️❌'.split('').filter(e => e === '✔️').length // 0

因为✔️需要两个字符: "✔️".length === 2

我认为

"✔️"[0] === "✔" "✔️"[1] 表示颜色。

"❌".length === 1所以它只需要一个字符。

这与不同肤色的表情符号的工作方式类似。

至于如何比较,我认为 "✔️".codePointAt(0)(不要与 charCodeAt() 混淆)可能会有所帮助。见 https://thekevinscott.com/emojis-in-javascript/:

codePointAt and fromCodePoint are new methods introduced in ES2015 that can handle unicode characters whose UTF-16 encoding is greater than 16 bits, which includes emojis. Use these instead of charCodeAt, which doesn’t handle emoji correctly.

我认为“✔️”由 2 个部分组成。当你输出'✔️'[0]时你得到'✔',黑色勾号不等于绿色勾号。

然而,'❌' 仅由一个组件组成,因此当您输出 '❌'[0] 时,您会得到相同的结果:'❌'。

第二个字符 '✔️'[1](代码点 = 65039)是 Variation Selector

A Variation Selector specifies that the preceding character should be displayed with emoji presentation. Only required if the preceding character defaults to text presentation.

Often used in Emoji ZWJ Sequences, where one or more characters in the sequence have text and emoji presentation, but otherwise default to text (black and white) display.

Examples Snowman as text: ☃. Snowman as Emoji: ☃️

Black Heart as text: ❤. Black Heart as Emoji: ❤️ (not so black)

Variation Selector-16 was approved as part of Unicode 3.2 in 2002.

https://unicode-table.com/en/FE0F/