我正在使用这个字符,双重升高音''
,它的unicode编码是0x1d12a。
如果我在字符串中使用它,我无法得到正确的字符串长度:
str = "F"
str.length // returns 3, even though there are 2 characters!
我该如何使函数返回正确的答案,无论是否使用特殊的Unicode字符?
我正在使用这个字符,双重升高音''
,它的unicode编码是0x1d12a。
如果我在字符串中使用它,我无法得到正确的字符串长度:
str = "F"
str.length // returns 3, even though there are 2 characters!
我该如何使函数返回正确的答案,无论是否使用特殊的Unicode字符?
String.prototype.codes = function() { return [...this].length };
String.prototype.chars = function() {
let GraphemeSplitter = require('grapheme-splitter');
return (new GraphemeSplitter()).countGraphemes(this);
}
console.log("F".codes()); // 2
console.log("❤️".codes()); // 8
console.log("❤️".codes()); // 2
console.log("F".chars()); // 2
console.log("❤️".chars()); // 1
console.log("❤️".chars()); // 1
"F"
is encoded in UTF-16 using 3 (not 2) codeunits: 0x0046 0xD834 0xDD2A
. "❤️"
is encoded using 2 codeunits: 0x2764 0xFE0F
. "❤️"
is encoded using 9 (not 8) codeunits: 0xD83D 0xDC69 0x200D 0x2764 0xFE0F 0x200D 0xD83D 0xDC8B 0x200D
- Remy Lebeaufunction nbUnicodeLength(string){
var stringIndex = 0;
var unicodeIndex = 0;
var length = string.length;
var second;
var first;
while (stringIndex < length) {
first = string.charCodeAt(stringIndex); // returns an integer between 0 and 65535 representing the UTF-16 code unit at the given index.
if (first >= 0xD800 && first <= 0xDBFF && string.length > stringIndex + 1) {
second = string.charCodeAt(stringIndex + 1);
if (second >= 0xDC00 && second <= 0xDFFF) {
stringIndex += 2;
} else {
stringIndex += 1;
}
} else {
stringIndex += 1;
}
unicodeIndex += 1;
}
return unicodeIndex;
}
总结我的评论:
那只是该字符串的长度。
有些字符涉及到其他字符,即使看起来像一个单独的字符。"̉mủt̉ả̉̉̉t̉ẻd̉W̉ỏ̉r̉̉d̉̉".length == 24
从这篇(很棒的)博客文章中,他们有一个函数可以返回正确的长度:
function fancyCount(str){
const joiner = "\u{200D}";
const split = str.split(joiner);
let count = 0;
for(const s of split){
//removing the variation selectors
const num = Array.from(s.split(/[\ufe00-\ufe0f]/).join("")).length;
count += num;
}
//assuming the joiners are used appropriately
return count / split.length;
}
console.log(fancyCount("F") == 2) // true
console.log([..."F"].length); // 2
- daximfor (let i = 0; i < 0x110000; i++) {let c = String.fromCodePoint(i); console.log([...c].length, c);}
- daximJavascript(和Java)字符串采用UTF-16编码。
Unicode代码点U+0046(F
)使用1个代码单元进行UTF-16编码:0x0046
Unicode代码点U+1D12A()使用2个代码单元(称为“代理对”)进行UTF-16编码:
0xD834 0xDD2A
这就是为什么你得到的是长度为3而不是2。 length
计算的是编码后的代码单元数量,而不是Unicode代码点的数量。