【问题标题】:Why is '\u{1D11E}'.charAt(0) not equal to '\u{1D11E}'?为什么'\u{1D11E}'.charAt(0) 不等于'\u{1D11E}'?
【发布时间】:2020-07-22 07:04:59
【问题描述】:

当我试图在控制台中评估这个表达式时,我得到了false,为什么?

console.log('\u{1D11E}'.charAt(0) === '\u{1D11E}')

【问题讨论】:

  • 请解决您的问题。这只是一段无格式的无效语法。
  • 因为charAt只能处理UTF-16,
  • 因为charAt()原本是设计为只支持BMP的,而你给的字符不属于BMP。查看this section 了解详细信息(和补救措施)。
  • 这里有类似的问题:stackoverflow.com/q/46157867/3650856。您将右侧的 unicode 字符与左侧的非 unicode 字符进行比较。 charAt(0) 将分解 unicode 字符,因为它是更长的字节。因此它们的值不同,只有相同的类型。
  • @raina77ow 另一个选项是在字符串上使用Array.from,并对其进行索引。不知道为什么 MDN 没有提到这一点。

标签: javascript unicode utf


【解决方案1】:

'\u{1D11E}' 是由单个 Unicode codepoint U+1D11E 组成的字符串。字符串以 UTF-16 格式编码。所以字符串中的每个char 都是一个UTF-16 代码单元。因此charAt() 返回一个代码单元,而不是一个代码点。

U+1D11E 在 UTF-16 中编码为 0xD834 0xDD1E,因此字符串 '\u{1D11E}' 实际上是 '\uD834\uDD1E',因此:

'\u{1D11E}'.charAt(0) === '\u{1D11E}' // false
// aka: '\uD834' === '\u{1D11E}'

'\u{1D11E}'.charAt(0) === '\uD834' // true
// aka: '\uD834' === '\uD834'

【讨论】:

    【解决方案2】:

    一个简单的 console.log 会告诉你问题

    console.log('\u{1D11E}'.charAt(0))
    console.log('\u{1D11E}')
    console.log('\u{1D11E}'.charAt(0) === '\u{1D11E}')

    如您所见,它们没有给出相同的结果,这是因为 charAt 只处理 UTF-16 code units。有关如何处理 UTF-16 字符(也在其他平面上,因此代码点 > 65535),请参阅同一来源的代码 sn-p。

    【讨论】:

    • 嗨,但是当 '\u{1D11E}'.chartAt(0) === '\uD834' 并且结果为真时
    • @JsonPrime 同样的想法,console.log 每一个,你会明白为什么。他们都回来了……
    • 好的,因为它们都返回 �,所以 '\u{1D11E}'.chartAt(0) === '\uD834' 的结果是 true ,对吗?
    • @JsonPrime 是 charAt 不是 chartAt,是的
    • 解释错误:'\u{1D11E} 是一个 UTF-16 字符(或者更好的是 UTF-16 码位)。 MDN 使用 code unit(这是 Unicode 中很少使用的符号)。在这种情况下,charAt(0) 给出了一个代码单元,它是一个代理项,因此不是有效的 UTF-16 代码点(或字符)。
    猜你喜欢
    • 1970-01-01
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    • 2016-04-24
    相关资源
    最近更新 更多