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 事件的一些重要说明
Oct 25 Javascript
jquery获得页面元素的坐标值实现思路及代码
Apr 15 Javascript
jsp js鼠标移动到指定区域显示选项卡离开时隐藏示例
Jun 14 Javascript
jQuery的text()方法用法分析
Dec 20 Javascript
javascript实现图片上传前台页面
Aug 18 Javascript
jquery京东商城双11焦点图多图广告特效代码分享
Sep 06 Javascript
jQuery插件实现适用于移动端的地址选择器
Feb 18 Javascript
关于微信上网页图片点击全屏放大效果
Dec 19 Javascript
Bootstrap里的文件分别代表什么意思及其引用方法
May 01 Javascript
Element DateTimePicker日期时间选择器的使用示例
Jul 27 Javascript
解决antd Form 表单校验方法无响应的问题
Oct 27 Javascript
javascript全局自定义鼠标右键菜单
Dec 08 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
Zend Framework分发器用法示例
2016/12/11 PHP
php-beanstalkd消息队列类实例分享
2017/07/19 PHP
Ajax中的JSON格式与php传输过程全面解析
2017/11/14 PHP
CSS+JS构建的图片查看器
2006/07/22 Javascript
jQuery选中select控件 无法设置selected的解决方法
2010/09/01 Javascript
Jquery 选中表格一列并对表格排序实现原理
2012/12/15 Javascript
JQuery 获取json数据$.getJSON方法的实例代码
2013/08/02 Javascript
学习JavaScript设计模式(继承)
2015/11/26 Javascript
js改变透明度实现轮播图的算法
2020/08/24 Javascript
Bootstrap基本样式学习笔记之图片(6)
2016/12/07 Javascript
详解JS中的attribute属性
2017/04/25 Javascript
Jquery获取radio选中的值
2017/05/05 jQuery
详解Angular 中 ngOnInit 和 constructor 使用场景
2017/06/22 Javascript
javascript中神奇的 Date对象小结
2017/10/12 Javascript
微信小程序表单验证功能完整实例
2017/12/01 Javascript
微信小程序学习总结(四)事件与冒泡实例分析
2020/06/04 Javascript
python定时器使用示例分享
2014/02/16 Python
pycharm 使用心得(七)一些实用功能介绍
2014/06/06 Python
Python可变参数*args和**kwargs用法实例小结
2018/04/27 Python
基于python OpenCV实现动态人脸检测
2018/05/25 Python
解决python3捕获cx_oracle抛出的异常错误问题
2018/10/18 Python
Python Subprocess模块原理及实例
2019/08/26 Python
python 多进程并行编程 ProcessPoolExecutor的实现
2019/10/11 Python
python将图片转base64,实现前端显示
2020/01/09 Python
python+selenium+chromedriver实现爬虫示例代码
2020/04/10 Python
HTML5实现锚点时请使用id取代name
2013/09/06 HTML / CSS
HTML5 canvas绘制的玫瑰花效果
2014/05/29 HTML / CSS
基于HTML5实现类似微信手机摇一摇功能(计算摇动次数)
2017/07/24 HTML / CSS
联想马亚西亚官方网站:Lenovo Malaysia
2018/09/19 全球购物
商务日语毕业生自荐信
2013/11/23 职场文书
大学军训感言1500字
2014/03/09 职场文书
教师节演讲稿
2014/05/06 职场文书
2015年项目工作总结
2015/04/29 职场文书
sql server删除前1000行数据的方法实例
2021/08/30 SQL Server
Redis特殊数据类型HyperLogLog基数统计算法讲解
2022/06/01 Redis
使用CSS实现音波加载效果
2023/05/07 HTML / CSS