标题过长使用javascript按字节截取字符串


Posted in Javascript onApril 24, 2014

做为一个前端开发人员在网页展示中经常会碰到,标题过长,需要截取字符串,用CSS的实现的话各种兼容问题,各种坑。

让后台程序截一下,又各种推托,让后台按字节截一下更是和要了后台老命一样,最后可能只会安字符长度给你截一下,最后不好看,对不齐,还是回头整CSS、调兼容;

有以上有感触的前端同学默默点个赞吧。

最近接触一个项目,后台只提供接口(json),所有页面的数据渲染,数据绑定都都交给了前端。终于,不考虑SEO,页面所有的主动权到偶的手中了,不经意间就碰到字节截取老问题了。

网络上流传一个Javascript简单获取字节长度的方法:

String.prototype.Blength = function(){//返回字符串字节长度 
return this.replace(/([^\x00-\xFF])/g, "aa").length; 
};

确实很简单,大于ASCII码的字符都算做两个字节,虽然严格来说不正确,但我们是用来辅助展示效果的,真严格起来反而不好了,

但总感觉为了一点投机取巧,而用正则这种较耗时东西不太好,其实也就节省了两行代码,所以我决定还是用正常方式计算:

function getBlength(str){ 
for(var i=str.length;i--;){ 
n += str.charCodeAt(i) > 255 ? 2 : 1; 
} 
return n; 
}

我并没有把方法扩展到String对像的原型上去,还是因为效率问题,以下是测试代码:
//扩展到String的prototype上 
String.prototype.Blength = function () { 
var str = this, 
n = 0; 
for (var i = str.length; i--; ) { 
n += str.charCodeAt(i) > 255 ? 2 : 1; 
} 
return n; 
} 
//给String对像增加一个方法 
String.getBlength = function (str) { 
for (var i = str.length, n = 0; i--; ) { 
n += str.charCodeAt(i) > 255 ? 2 : 1; 
} 
return n; 
} 
//先构造一个中英混合的长字符串 
var str = "javascript 高效按字节截取字符串方法 getBlengthjavascript 高效按字节截取字符串方法 getBlength"; 
str = str.replace(/./g, str).replace(/./g, str); 
console.log("创造的字符串长度为:",str.length) 
console.log("-------------测试开始--------------") 
console.log("str.Blength() >> ",str.Blength()) 
console.log("String.getBlength(str) >> ",String.getBlength(str)) 
console.log("--效率测试开始--") var time1 = new Date() 
for(var i=0;i<100;i++){ 
str.Blength() 
} 
console.log("Blength耗时:",new Date() - time1); 
var time2 = new Date() 
for(var i=0;i<100;i++){ 
String.getBlength(str) 
} 
console.log("getBlength耗时:",new Date() - time2);

结果效率差的不是一点半点,至于原因可能时间花费在了原型链的检索上了,我没有深究,知道的可以留言告诉我:

创造的字符串长度为: 314432
-------------测试开始--------------

str.Blength() >> 425408 
String.getBlength(str) >> 425408 
--效率测试开始-- 
Blength耗时: 1774 
getBlength耗时: 95

现在要截取字符串的基础函数有了,因为在这种情况下字符占的字节长度最长为2,所以用二分法来找到合适截取位置是再好不过了。

给一个效率应该算不错的截取函数:

//简单计算字节长度 
String.getBlength = function (str) { 
for (var i = str.length, n = 0; i--; ) { 
n += str.charCodeAt(i) > 255 ? 2 : 1; 
} 
return n; 
} 
//按指定字节截取字符串 
String.cutByte = function(str,len,endstr){ 
var len = +len 
,endstr = typeof(endstr) == 'undefined' ? "..." : endstr.toString(); 
function n2(a){ var n = a / 2 | 0; return (n > 0 ? n : 1)} //用于二分法查找 
if(!(str+"").length || !len || len<=0){return "";} 
if(this.getBlength(str) <= len){return str;} //整个函数中最耗时的一个判断,欢迎优化 
var lenS = len - this.getBlength(endstr) 
,_lenS = 0 
, _strl = 0 
while (_strl <= lenS){ 
var _lenS1 = n2(lenS -_strl) 
_strl += this.getBlength(str.substr(_lenS,_lenS1)) 
_lenS += _lenS1 
} 
return str.substr(0,_lenS-1) + endstr 
}

拿上面的字符串来测试一下,应该是载得越长越耗时,截个20W的长度试试:
console.log("创造的字符串长度为:",str.length," 字节长度为:",String.getBlength(str)) 
console.log("-------------测试开始--------------") 
console.log("String.cutByte('1开始1',6,'...') >> ",String.cutByte('1开始1',6,'...')) 
console.log("String.cutByte(str,12,'...') >> ",String.cutByte(str,12,'...')) 
console.log("String.cutByte(str,13,'..') >> ",String.cutByte(str,13,'..')) 
console.log("String.cutByte(str,14,'.') >> ",String.cutByte(str,14,'.')) 
console.log("String.cutByte(str,15,'') >> ",String.cutByte(str,15,'')) 
console.log("--效率测试开始--") 
var time1 = new Date() 
for(var i=0;i<100;i++){ 
String.cutByte(str,200000,'...') 
} 
console.log("耗时:",new Date() - time1);

输出结果:

创造的字符串长度为: 314432 字节长度为: 425408
-------------测试开始--------------

String.cutByte('1开始1',6,'...') >> 1开始1 
String.cutByte(str,12,'...') >> javascrip... 
String.cutByte(str,13,'..') >> javascript .. 
String.cutByte(str,14,'.') >> javascript 高. 
String.cutByte(str,15,'') >> javascript 高

--效率测试开始--
耗时: 155

其实把截取字符长度改到30W 40W的耗时也差不了多少,在二分法面前,这都是一个级别的

对比之前的计算字节长度的耗时,用二分法查找截取只消耗了不到两次字节长度的记算的时间.

最后,同学们,来挑战一下效率吧!

Javascript 相关文章推荐
javascript IE中的DOM ready应用技巧
Jul 23 Javascript
javascript中apply和call方法的作用及区别说明
Feb 14 Javascript
测试IE浏览器对JavaScript的AngularJS的兼容性
Jun 19 Javascript
jquery插件方式实现table查询功能的简单实例
Jun 06 Javascript
JS实现异步上传压缩图片
Apr 22 Javascript
jQuery操作之效果详解
May 19 jQuery
Vue.js划分组件的方法
Oct 29 Javascript
centos 上快速搭建ghost博客方法分享
May 23 Javascript
vue通信方式EventBus的实现代码详解
Jun 10 Javascript
vue 使用高德地图vue-amap组件过程解析
Sep 07 Javascript
vue resource发送请求的几种方式
Sep 30 Javascript
vue中实现点击空白区域关闭弹窗的两种方法
Dec 30 Vue.js
JS对img标签进行优化使用onerror显示默认图像
Apr 24 #Javascript
原生javascript模仿win8等待提示圆圈进度条
Apr 24 #Javascript
js如何判断用户是在PC端和还是移动端访问
Apr 24 #Javascript
jquery 扑捉回车键事件代码
Apr 24 #Javascript
IE中的File域无法清空使用jQuery重设File域
Apr 24 #Javascript
js 动态为textbox添加下拉框数据源的方法
Apr 24 #Javascript
from表单多个按钮提交用onclick跳转不同action
Apr 24 #Javascript
You might like
php GeoIP的使用教程
2011/03/09 PHP
非常好用的两个PHP函数 serialize()和unserialize()
2012/02/04 PHP
php实现12306余票查询、价格查询示例
2014/04/17 PHP
php实现获取局域网所有用户的电脑IP和主机名、及mac地址完整实例
2014/07/18 PHP
PHP页面实现定时跳转的方法
2014/10/31 PHP
php实现的用户查询类实例
2015/06/18 PHP
关于jQuery参考实例 1.0 jQuery的哲学
2013/04/07 Javascript
node.js正则表达式获取网页中所有链接的代码实例
2014/06/03 Javascript
JavaScript返回网页中超链接数量的方法
2015/04/03 Javascript
javascript中的作用域和闭包详解
2016/01/13 Javascript
jQuery基于toggle实现click触发DIV的显示与隐藏问题分析
2016/06/12 Javascript
详解javascript表单的Ajax提交插件的使用
2016/12/29 Javascript
JS实现的简单四则运算计算器功能示例
2017/09/27 Javascript
Vue.js实现的购物车功能详解
2019/01/27 Javascript
IE11下CKEditor在Bootstrap Modal中下拉问题的解决
2019/09/25 Javascript
原生JS实现烟花效果
2020/03/10 Javascript
vue祖孙组件之间的数据传递案例
2020/12/07 Vue.js
[01:25]DOTA2超级联赛专访iG 将调整状态找回自己
2013/06/05 DOTA
[51:00]Secret vs VGJ.S 2018国际邀请赛淘汰赛BO3 第一场 8.24
2018/08/25 DOTA
利用python解决mysql视图导入导出依赖的问题
2017/12/17 Python
Django REST为文件属性输出完整URL的方法
2017/12/18 Python
Python实现将doc转化pdf格式文档的方法
2018/01/19 Python
python散点图实例之随机漫步
2018/08/27 Python
对python过滤器和lambda函数的用法详解
2019/01/21 Python
在SQLite-Python中实现返回、查询中文字段的方法
2019/07/17 Python
pycharm编写spark程序,导入pyspark包的3中实现方法
2019/08/02 Python
python getopt模块使用实例解析
2019/12/18 Python
python的链表基础知识点
2020/09/13 Python
PyCharm 解决找不到新打开项目的窗口问题
2021/01/15 Python
JAVA程序员面试题
2012/10/03 面试题
优秀团员事迹材料2000字
2014/08/20 职场文书
群众路线教育实践活动方案
2014/10/31 职场文书
2015年安全员工作总结范文
2015/04/22 职场文书
2016年五一劳动节专题校园广播稿
2015/12/17 职场文书
优质护理心得体会
2016/01/22 职场文书
MySQL 使用事件(Events)完成计划任务
2021/05/24 MySQL