标题过长使用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 相关文章推荐
jQuery循环滚动展示代码 可应用到文字和图片上
May 11 Javascript
ie8 不支持new Date(2012-11-10)问题的解决方法
Jul 31 Javascript
解决用jquery load加载页面到div时,不执行页面js的问题
Feb 22 Javascript
js实现鼠标悬停图片上时滚动文字说明的方法
Feb 17 Javascript
js控制文本框只输入数字和小数点的方法
Mar 10 Javascript
Javascript之BOM(window对象)详解
May 25 Javascript
JS获取字符串实际长度(包含汉字)的简单方法
Aug 11 Javascript
JavaScript文件的同步和异步加载的实现代码
Aug 19 Javascript
详解webpack babel的配置
Jan 09 Javascript
vue3.0 CLI - 1 - npm 安装与初始化的入门教程
Sep 14 Javascript
如何基于layui的laytpl实现数据绑定的示例代码
Apr 10 Javascript
浅析JavaScript 函数柯里化
Sep 08 Javascript
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
推荐几款用 Sublime Text 开发 Laravel 所用到的插件
2014/10/30 PHP
php按单词截取字符串的方法
2015/04/07 PHP
php类常量用法实例分析
2015/07/09 PHP
PHP使用file_get_content设置头信息的方法
2016/02/14 PHP
非常经典的PHP文件上传类分享
2016/05/15 PHP
PHP实现QQ、微信和支付宝三合一收款码实例代码
2018/02/19 PHP
PHP实现二维数组中的查找算法小结
2018/06/09 PHP
jQuery EasyUI NumberBox(数字框)的用法
2010/07/08 Javascript
js中settimeout方法加参数的使用实例
2014/02/27 Javascript
Javascript核心读书有感之类型、值和变量
2015/02/11 Javascript
Vue原理剖析 实现双向绑定MVVM
2017/05/03 Javascript
easyui-datagrid开发实践(总结)
2017/08/02 Javascript
Node.js如何使用Diffie-Hellman密钥交换算法详解
2017/09/05 Javascript
Vue 后台管理类项目兼容IE9+的方法示例
2019/02/20 Javascript
layui 数据表格复选框实现单选功能的例子
2019/09/19 Javascript
Vue实现购物车基本功能
2020/11/08 Javascript
Django的分页器实例(paginator)
2017/12/01 Python
解决python读取几千万行的大表内存问题
2018/06/26 Python
Python wxPython库使用wx.ListBox创建列表框示例
2018/09/03 Python
完美解决keras保存好的model不能成功加载问题
2020/06/11 Python
python文件编写好后如何实践
2020/07/07 Python
python实现简单贪吃蛇游戏
2020/09/29 Python
css3 iphone玻璃透明气泡完美实现
2013/03/20 HTML / CSS
目前不被任何主流浏览器支持的CSS3属性汇总
2014/07/21 HTML / CSS
在职研究生自我鉴定
2013/10/16 职场文书
迟到检讨书400字
2014/01/13 职场文书
母亲80寿诞答谢词
2014/01/16 职场文书
企业授权委托书范本
2014/04/02 职场文书
公安局副政委班子个人对照检查材料
2014/10/04 职场文书
刑事和解协议书范本
2014/11/19 职场文书
材料员岗位职责范本
2015/04/11 职场文书
董事长新年致辞
2015/07/29 职场文书
Java数组与堆栈相关知识总结
2021/06/29 Java/Android
JavaWeb 入门篇(3)ServletContext 详解 具体应用
2021/07/16 Java/Android
javascript之Object.assign()的痛点分析
2022/03/03 Javascript
Golang bufio详细讲解
2022/04/21 Golang