标题过长使用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/FF)
Apr 02 Javascript
图片onload事件触发问题解决方法
Jul 31 Javascript
JQuery slideshow的一个小问题(如何发现及解决过程)
Feb 06 Javascript
JS 毫秒转时间示例代码
Sep 22 Javascript
js实现遮罩层弹出框的方法
Jan 15 Javascript
jQuery里filter()函数与find()函数用法分析
Jun 24 Javascript
js获取所有checkbox的值的简单实例
May 30 Javascript
js判断数组key是否存在(不用循环)的简单实例
Aug 03 Javascript
node.js中module.exports与exports用法上的区别
Sep 02 Javascript
详解从Vue.js源码看异步更新DOM策略及nextTick
Oct 11 Javascript
ES6解构赋值的功能与用途实例分析
Oct 31 Javascript
使用JS监听键盘按下事件(keydown event)
Nov 07 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
PHP 判断常量,变量和函数是否存在
2009/04/26 PHP
关于Zend Studio 配色方案插件的介绍
2013/06/24 PHP
PHP中大括号'{}'用法实例总结
2017/02/08 PHP
老生常谈php 正则中的i,m,s,x,e分别表示什么
2017/03/02 PHP
php7基于递归实现删除空文件夹的方法示例
2017/06/15 PHP
PHP whois查询类定义与用法示例
2019/04/03 PHP
JavaScript网页制作特殊效果用随机数
2007/05/22 Javascript
jQuery-Easyui 1.2 实现多层菜单效果的代码
2012/01/13 Javascript
js arguments,jcallee caller用法总结
2013/11/30 Javascript
微信小程序  modal弹框组件详解
2016/10/27 Javascript
Angular+Node生成随机数的方法
2017/06/16 Javascript
Angular.js中上传指令ng-upload的基本使用教程
2017/07/30 Javascript
bootstrap-table实现服务器分页的示例 (spring 后台)
2017/09/01 Javascript
nodejs发送http请求时遇到404长时间未响应的解决方法
2017/12/10 NodeJs
js Element Traversal规范中的元素遍历方法
2018/04/19 Javascript
js实现课堂随机点名系统
2019/11/21 Javascript
three.js 利用uv和ThreeBSP制作一个快递柜功能
2020/08/18 Javascript
Vue中使用Echarts仪表盘展示实时数据的实现
2020/11/01 Javascript
JavaScript实现原型封装轮播图
2020/12/27 Javascript
深入理解javascript中的this
2021/02/08 Javascript
[44:39]2014 DOTA2国际邀请赛中国区预选赛 NE VS CNB
2014/05/21 DOTA
[03:53]2016国际邀请赛中国区预选赛第三日TOP10精彩集锦
2016/06/29 DOTA
用python的requests第三方模块抓取王者荣耀所有英雄的皮肤实例
2017/12/14 Python
Python定时任务sched模块用法示例
2018/07/16 Python
用Django写天气预报查询网站
2018/10/21 Python
CSS3的resize属性使用初探
2015/09/27 HTML / CSS
在HTML5 Canvas中放入图片和保存为图片的方法
2014/05/03 HTML / CSS
HTML table 表格边框的实现思路
2019/10/12 HTML / CSS
介绍下Java的输入输出流
2014/01/22 面试题
历史教育专业个人求职信
2013/12/13 职场文书
爱心捐款倡议书范文
2014/05/12 职场文书
房地产广告策划方案
2014/05/15 职场文书
小学生自我评价100字(15篇)
2014/09/18 职场文书
计划生育诚信协议书
2014/11/02 职场文书
团代会闭幕词
2015/01/28 职场文书
毕业欢送会致辞
2015/07/29 职场文书