用JS怎样才能正确的得到字符串的长度?

var s = '吉林?';
s.length; //4

用js输出s.length的是4,但是变量s的字符串的个数是3,如何通过代码准确得到变量 s 的字符串个数(3)?

阅读 5.9k
8 个回答

s.match(/[\s\S]/gu).length
主要是正则表达式u标志符可以匹配4字节 Unicode 编码。
空字符串要处理一下。。。因为 match 返回 null


正则表达式u是ES6的特性,同样的ES6的字符串迭代器也能正确处理 Unicode 编码:[...s].length等等写法。

我好奇地跑去 babel 测试了一下,发现了这群大触丧病的 hack:

s.match(/[\s\S]/gu)

s.match(/(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g)

忽略了中间有空格的情况,仅统计汉字:
方法一

var s = '吉 林 ?';
console.log(s.match(/[\u4e00-\u9fa5]/g).length + s.match(/[\u9fa6-\uffff]/g).length / 2);
输出:3

方法二

var s = '吉 林 ?';
console.log(s.replace(/\s+/g, "").match(/\s|\S/gu).length);
输出:3

不忽略空格的情况:

var s = '吉 林 ?';
console.log(s.match(/\s|\S/gu).length);
输出:5

引子
虽然我没有正确答案,但是可以提供一点线索.
犀牛书上看到.淘宝前端翻译的第6版39页

理论基础
js里面的字符串是采用utf-16编码的unicode字符集.
可以这样理解,一个字符等价于一个16位值unicode字符
所有针对字符串的操作,实际上是对unicode进行操作.

但是,最常用的unicode根本无法容纳地球上所有文字,所以有些字符必须用两个unicode表示..因此,这种字符的长度就是2.

实验
吉林?
转换成unicode字符的结果是
\u5409\u6797\ud842\udfb7

看吧,3个汉字实际上是4个unicode了....长度就肯定是4呀

解决
开始我还以为是两个吉林的吉字呢.....
结果仔细看,第3个字是个特殊字符...难怪常用的unicode不包含它呢.所以用了2个nunicode来表示...

这个时候就不能使用js自带的方法来处理字符串啦,因为这些方法实际上处理unicode的方法,而不是处理汉字的方法..
就要找一个处理汉字的方法..就像一楼说的那样...

处理4字节的unicode.相当于是utf-32编码的字符集...就完全能够代表所有的汉字及特殊字符啦

最后一个字符是特殊字符,长度是2.
你可以用正则将特殊字符匹配出来,然后算其他字符的长度最后再加上特殊字符的个数。

function getStrLen (str) {
  let s = 0 ;
  if (str !== undefined && str !== null) {
    s = str.match(/\s|\S/gu).length
  }
  return s
}
escape('吉林?').toLocaleLowerCase().replace(/%u/gi,'\\u');
// "\u5409\u6797\ud842\udfb7"

特殊字符,用正则吧

推荐问题
宣传栏