Prototype源码浅析 String部分(一)之有关indexOf优化


Posted in Javascript onJanuary 15, 2012

添加到String.prototype中的方法比较多,不过归结起来,大致分为下面几类:

分类 方法名 
原始能力增强               strip |  include  |  startsWith  |  endsWith |  empty |  blank
格式 camelize | capitalize |  underscore |  dasherize  | inspect          
变形 toArray |  succ  | times
替换 interpolate  | sub |  scan |  truncate | gsub
HTML处理 stripTags  | escapeHTML |  unescapeHTML
参数序列化 toQueryParams
JSON处理 unfilterJSON |  isJSON |  evalJSON |  parseJSON
脚本处理 stripScripts |  extractScripts  | evalScripts

从基本的原始能力增强开始,下面是具体的实现,这一段很好理解的:

(function(s){ 
function strip(){ 
return this.replace(/^\s+/,'').replace(/\s+$/,''); 
} 
function include(pattern){ 
return this.indexOf(pattern) > -1;//split 
} 
function startsWith(pattern) { 
return this.lastIndexOf(pattern, 0) === 0; 
} 
function endsWith(pattern) { 
var d = this.length - pattern.length; 
return d >= 0 && this.indexOf(pattern, d) === d; 
} 
function empty() { 
return this == ''; 
} 
function blank() { 
return /^\s*$/.test(this); 
} 
s.strip = String.prototype.trim || strip; 
s.include = include; 
s.startsWith = startsWith; 
s.endsWith = endsWith; 
s.empty = empty; 
s.blank = blank; 
})(String.prototype);

上面的strip在jquery里面是$.trim,而且大部分貌似都是trim。这里直接扩展原生原型的悲剧之处就显现出来了,因为后面的JS实现中(比如chrome)就实现了trim方法,那就弄巧成拙了。
function strip(){ 
return this.replace(/^\s+/,'').replace(/\s+$/,''); 
}

这里面的replace(/^\s+/,'')就是trimLeft,replace(/\s+$/,'')是trimRight,不过Prototype.String中没有这两个方法。

下面是这一部分比较有意思的地方:

当时看这段的时候,对其中的startsWith和endsWith甚是不解,按理来说,startsWith用indexOf就可以了,这里却是用的lastIndexOf。后来去翻了一下Prototype1.6版本的实现:

function startsWith(pattern) { 
return this.indexOf(pattern) === 0; 
} function endsWith(pattern) { 
var d = this.length - pattern.length; 
return d >= 0 && this.lastIndexOf(pattern) === d; 
}

可见,以前版本中startsWith用的就是indexOf,不过1.7版本修改了startsWith的实现。在1.7版本中:

startsWith实现中lastIndexOf从后向前查找,不过起点(fromindex)设置为0,因此,只需要检测开头一次就可以了。
endsWith实现中indexOf从前向后查找,由于字符串长度不定,因此这里计算了一下长度,然后再确定了起点(fromindex),因此也只需要检测结尾一次就可以了。

这里的性能优化之处在于,1.6的实现中,如果开头没有匹配(就是startsWith不成立),但是indexOf依旧会向后查找,直到找到一个匹配的或者字符串结尾,这样就浪费了。举个例子,对于下面的一个操作:

'abcdefgabcdefg'.startsWith('abc')
在1.6版本和1.7版本的实现中,没有任何区别,但是我们转换一下:

'abcdefgabcdefg'.startsWith('xesam')
在1.6实现中,startsWith内部的indexOf操作会在开头的a没有和x匹配后,虽然没有必要再继续了,但是indexOf依旧会继续向后查找,直到找到匹配的‘xesam'或者字符串末尾。
在1.7实现中,startsWith内部的lastIndexOf是反向查找的(fromIndex=0),因此在开头的a没有和x匹配后,操作就停止了,因为lastIndexOf已经到头了。
这么一对比,如果待检测的字符串非常长的话,两种实现方式的效率会有明显的区别。
endsWith的原理也是一样的。

Javascript 相关文章推荐
JavaScript面象对象设计
Apr 28 Javascript
ExtJS Store的数据访问与更新问题
Apr 28 Javascript
Ajax执行顺序流程及回调问题分析
Dec 10 Javascript
js获取域名的方法
Jan 27 Javascript
JavaScript获取网页表单action属性的方法
Apr 02 Javascript
JavaScript实现的经典文件树菜单效果
Sep 08 Javascript
jQuery 获取select选中值及清除选中状态
Dec 13 Javascript
Bootstrap中data-target 到底是什么
Feb 14 Javascript
在node中如何使用 ES6
Apr 22 Javascript
基于vue2框架的机器人自动回复mini-project实例代码
Jun 13 Javascript
layui监听工具栏的实例(操作列表按钮)
Sep 10 Javascript
Vue点击切换Class变化,实现Active当前样式操作
Jul 17 Javascript
用js小类库获取浏览器的高度和宽度信息
Jan 15 #Javascript
javascript 文本框水印/占位符(watermark/placeholder)实现方法
Jan 15 #Javascript
jQuery-Easyui 1.2 实现多层菜单效果的代码
Jan 13 #Javascript
20个最新的jQuery插件
Jan 13 #Javascript
JSON 数据格式介绍
Jan 13 #Javascript
ASP.NET jQuery 实例6 (实现CheckBoxList成员全选或全取消)
Jan 13 #Javascript
ASP.NET jQuery 实例5 (显示CheckBoxList成员选中的内容)
Jan 13 #Javascript
You might like
php遍历目录viewDir函数
2009/12/15 PHP
Chrome Web App开发小结
2014/09/04 PHP
php支持断点续传、分块下载的类
2016/05/02 PHP
php is_writable判断文件是否可写实例代码
2016/10/13 PHP
thinkphp框架实现路由重定义简化url访问地址的方法分析
2020/04/04 PHP
延时重复执行函数 lLoopRun.js
2007/05/08 Javascript
innertext , insertadjacentelement , insertadjacenthtml , insertadjacenttext 等区别
2007/06/29 Javascript
JavaScript 学习小结(适合新手参考)
2009/07/30 Javascript
JQuery制作的放大效果的popup对话框(未添加任何jquery plugin)分享
2013/04/28 Javascript
javascript中数组中求最大值示例代码
2013/12/18 Javascript
JavaScript简单实现鼠标拖动选择功能
2014/03/06 Javascript
javascript面向对象之访问对象属性的两种方式分析
2015/01/13 Javascript
修复jQuery tablesorter无法正确排序的bug(加千分位数字后)
2016/03/30 Javascript
详解利用exif.js解决ios手机上传竖拍照片旋转90度问题
2016/11/04 Javascript
JavaScript 总结几个提高性能知识点(推荐)
2017/02/20 Javascript
ES6新特性一: let和const命令详解
2017/04/20 Javascript
使用node.js实现微信小程序实时聊天功能
2018/08/13 Javascript
VUE DOM加载后执行自定义事件的方法
2018/09/07 Javascript
VuePress 快速踩坑小结
2019/02/14 Javascript
JS实现横向跑马灯效果代码
2020/04/20 Javascript
vue+AI智能机器人回复功能实现
2020/07/16 Javascript
Python实现在matplotlib中两个坐标轴之间画一条直线光标的方法
2015/05/20 Python
详解Python中的Cookie模块使用
2015/07/06 Python
Python 爬虫多线程详解及实例代码
2016/10/08 Python
Python实现视频下载功能
2017/03/14 Python
Python turtle绘画象棋棋盘
2019/08/21 Python
Python完全识别验证码自动登录实例详解
2019/11/24 Python
浅谈django 模型类使用save()方法的好处与注意事项
2020/03/28 Python
Python使用文件操作实现一个XX信息管理系统的示例
2020/07/02 Python
以色列的身体护理及家居香薰品牌:Sabon NYC
2018/02/23 全球购物
联想C++笔试题
2012/06/13 面试题
文明风采获奖感言
2014/02/18 职场文书
电子工程专业毕业生求职信
2014/03/14 职场文书
生产助理岗位职责
2014/06/18 职场文书
2015年发展党员工作总结报告
2015/03/31 职场文书
postgresql 删除重复数据案例详解
2021/08/02 PostgreSQL