传说有个很长的标题 “#%*……&#什么东西1234abcd 还不够长9876 efgh 好了就这样吧” ,标题有多长往往是不可预期的,比如日志的标题,用户还真有这么变态的,当然我们显示的时候,根据设计,不可能有多长显示多长,太长了屏幕也不够啊。
这个需求涉及到 获取string的长度 和 截取某个长度
搜了下相关资料,发现有人这么判断是否为双字节字符:
if(str.charCodeAt(i) & 0xff00) != 0){
//双字节
}
charCodeAt()用于获取指定位置字符的 Unicode 编码;
0xff00是 “1111 1111 0000 0000” 的十六进制表示法;
&(与操作) 的计算方式为: 见0得0,全1得1;
来做个小练习:
1. "中"的 Unicode 编码为20013,求20013 & 0xff00
第一个问题的是20013的二进制怎么求?坑爹的我根本不会,也不想去算,所谓的十进制转二进制,在JS里是这样的:
20013..toString(2); //你没看错, 就是两个 .
(20013).toString(2);
据同事说是ECMA里这么规定的操作符,好吧,我对文档无爱。
计算结果为:100 1110 0010 1101
结果再从二进制换成十进制,怎么换?
parseInt('0100111000000000', 2)
最终为: 19968
2. "a"的Unicode编码为97,求97 & 0xff00
97的二进制表示法为: 110 0001
不用再换十进制了,是个人都能看出结果为 0
到这里,想必大家都清楚为什么这样写了,单字节的Unicode编码的二进制最多只有八位,与操作后,结果一定是0。那么单字节最大的Unicode是多少,1111 1111转换后等于255。
来见识一下传说中的255是什么
String.fromCharCode(255); // ÿ
再来看看传说中的256是什么
String.fromCharCode(256); // Ā
好了,既然判断Unicode编码大于255就能确定是双字节,我就写的直接一点:
/**
* @param {string} str 要截取的字符串
*/
var getStrSize = function(str){
var size = 0;
for(var i = 0, len = str.length; i < len; i++){
if (str.charCodeAt(i) > 255){
size += 2;
}else{
size++;
}
}
return size;
};
/**
* @param {string} str 要截取的字符串
* @param {number} size 截取长度(单字节长度)
*/
var subStr = function(str, size){
var curSize = 0, arr = [];
for(var i = 0, len = str.length; i < len; i++){
arr.push(str.charAt(i));
if (str.charCodeAt(i) > 255){
curSize += 2;
if(size === curSize || size === curSize - 1){
return arr.join('');
}
}else{
curSize++;
if(size === curSize){
return arr.join('');
}
}
}
};
测试一下:
var str = '#%*……&#什么东西1234abcd 还不够长9876 efgh 好了就这样吧';
console.log(str.length);
console.log(getStrSize(str));
console.log(str.substr(0, 15));
console.log(subStr(str, 15));
输出:
更新:最近有个新需求,如果字符串包含标签,如 '这是一个<span class="red">标题</span>,打开看看吧' ,我要截断显示10个字符,那么就不是这么简单了
解决办法: 传送门