截断显示长字符串
传说有个很长的标题 “#%*……&#什么东西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));
输出:
40
56
#%*……&#什么东西1234
#%*……&#什么东
更新:最近有个新需求,如果字符串包含标签,如 '这是一个<span class="red">标题</span>,打开看看吧' ,我要截断显示10个字符,那么就不是这么简单了
解决办法:传送门