今天在使用KingFusion开发MES系统的过程中,遇到需要获取字符串有几位的判断;
在 JavaScript 中获取字符串的 “位数”(字符数)有多种方法,核心区别在于是否能正确处理 Unicode 特殊字符(如 emoji、生僻字)。
以下是详细解析和最佳实践:
一、最常用:length属性(基础场景)
语法
字符串.length说明
- 这是 JavaScript 原生提供的只读属性,不是方法,无需加括号
- 计数规则:按UTF-16 代码单元统计,每个 BMP 平面(基本多语言平面)字符占 1 个代码单元
- 适用场景:仅包含 ASCII 字符、中文、日文、韩文等常见字符的字符串
示例
console.log("abc".length); // 3(英文字母) console.log("你好世界".length); // 4(中文) console.log("123456".length); // 6(数字) console.log("a1b2c3".length); // 6(混合)二、⚠️ 致命坑点:length对特殊字符计数错误
length无法正确识别占 2 个 UTF-16 代码单元的字符,会导致计数翻倍:
- Emoji 表情(如😀、❤️、👍)
- 生僻汉字(如𠮷、𠮶、𠹌)
- 特殊符号(如𝄞、𝅘𝅥𝅮)
错误示例
console.log("😀".length); // 2(实际1个字符) console.log("👍❤️".length); // 4(实际2个字符) console.log("𠮷".length); // 2(实际1个生僻字) console.log("a😀b".length); // 4(实际3个字符)三、正确获取所有字符数(含特殊字符)
方法 1:ES6 扩展运算符[...str].length(推荐)
利用 ES6 的迭代器特性,能正确拆分 Unicode 字符,性能优秀且写法简洁。
console.log([..."😀"].length); // 1(正确) console.log([..."👍❤️"].length); // 2(正确) console.log([..."a😀b"].length); // 3(正确) console.log([..."𠮷𠮶𠹌"].length); // 3(正确)方法 2:Array.from(str).length(兼容性更好)
功能与扩展运算符完全一致,对旧环境的兼容性略好(需 ES6 支持)。
console.log(Array.from("😀😃😄").length); // 3 console.log(Array.from("你好😀世界").length); // 5方法 3:正则表达式/./u匹配(备用)
使用带u标志的正则表达式匹配所有 Unicode 字符,再统计数量。
function getCharCount(str) { return (str.match(/./gu) || []).length; } console.log(getCharCount("😀👍❤️")); // 3 console.log(getCharCount("")); // 0(空字符串处理)四、拓展:获取字符串的字节数
如果需要获取字符串的字节长度(而非字符数),不同编码下结果不同:
1. UTF-8 字节数(最常用)
function getUtf8ByteLength(str) { return new TextEncoder().encode(str).length; } console.log(getUtf8ByteLength("abc")); // 3(1字节/字符) console.log(getUtf8ByteLength("你好")); // 6(3字节/中文字符) console.log(getUtf8ByteLength("😀")); // 4(4字节/emoji)2. UTF-16 字节数(与length对应)
function getUtf16ByteLength(str) { return str.length * 2; } console.log(getUtf16ByteLength("abc")); // 6 console.log(getUtf16ByteLength("😀")); // 4五、方法对比与最佳实践
| 方法 | 正确处理特殊字符 | 性能 | 兼容性 | 适用场景 |
|---|---|---|---|---|
str.length | ❌ | 极高 | 所有浏览器 | 仅含常见字符的简单场景 |
[...str].length | ✅ | 高 | ES6+(现代浏览器) | 绝大多数业务场景(推荐) |
Array.from(str).length | ✅ | 高 | ES6+ | 与扩展运算符一致 |
正则/./u | ✅ | 中 | ES6+ | 特殊正则匹配场景 |
TextEncoder | - | 中 | 现代浏览器 | 需要 UTF-8 字节数时 |
通用最佳实践
// 封装一个通用的字符数获取函数 function getStringLength(str) { // 空字符串处理 if (!str) return 0; // 优先使用扩展运算符 return [...str].length; } // 使用示例 console.log(getStringLength("你好😀世界123")); // 7六、常见业务场景注意事项
- 输入框字数限制:如果允许用户输入 emoji,绝对不能用
length,否则会出现 “输入 1 个 emoji 算 2 个字符” 的 bug - 字符串截断:截断包含 emoji 的字符串时,需用
Array.from拆分后再截取,避免截断到代理对中间导致乱码 - 后端交互:后端通常按 UTF-8 字节数限制长度,前端需提前用
TextEncoder计算并提示用户