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 相关文章推荐
仿校内登陆框,精美,给那些很厉害但是没有设计天才的程序员
Nov 24 Javascript
Pro JavaScript Techniques学习笔记
Dec 28 Javascript
jquery表单验证框架提供的身份证验证方法(示例代码)
Dec 27 Javascript
javascript实现类似超链接的效果
Dec 26 Javascript
jQuery浏览器CSS3特写兼容实例
Jan 19 Javascript
微信支付如何实现内置浏览器的H5页面支付
Sep 25 Javascript
JS实现页面进入和返回定位到具体位置
Dec 08 Javascript
简单实现js放大镜效果
Jul 24 Javascript
prototype.js简单实现ajax功能示例
Oct 18 Javascript
vue checkbox 全选 数据的绑定及获取和计算方法
Feb 09 Javascript
js使用cookie实现记住用户名功能示例
Jun 13 Javascript
vue实现公告栏文字上下滚动效果的示例代码
Jun 16 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 header功能的使用
2013/10/28 PHP
ThinkPHP使用UTFWry地址库进行IP定位实例
2014/04/01 PHP
Yii2如何批量添加数据
2016/05/17 PHP
php注册和登录界面的实现案例(推荐)
2016/10/24 PHP
ThinkPHP删除栏目(实现批量删除栏目)
2017/06/21 PHP
php实现生成带二维码图片并强制下载功能
2018/02/24 PHP
JavaScript QueryString解析类代码
2010/01/17 Javascript
JS下拉框内容左右移动效果的具体实现
2013/07/10 Javascript
常用jQuery代码分享
2015/07/14 Javascript
JavaScript多线程详解
2015/08/12 Javascript
深入理解jQuery事件绑定
2016/06/02 Javascript
Bootstrap组件系列之福利篇几款好用的组件(推荐二)
2016/07/12 Javascript
js中字符型和数值型数字的互相转化方法(必看)
2017/04/25 Javascript
JS操作时间 - UNIX时间戳的简单介绍(必看篇)
2017/08/16 Javascript
vue-cli V3.0版本的使用详解
2018/10/24 Javascript
jQuery实现滑动星星评分效果(每日分享)
2019/11/13 jQuery
vue设置默认首页的操作
2020/08/12 Javascript
VSCode 添加自定义注释的方法(附带红色警戒经典注释风格)
2020/08/27 Javascript
NodeJS开发人员常见五个错误理解
2020/10/14 NodeJs
angular *Ngif else用法详解
2020/12/15 Javascript
[50:04]DOTA2上海特级锦标赛D组小组赛#2 Liquid VS VP第二局
2016/02/28 DOTA
一篇不错的Python入门教程
2007/02/08 Python
python删除指定类型(或非指定)的文件实例详解
2015/07/06 Python
Python字符编码判断方法分析
2016/07/01 Python
Python实现将Excel转换成xml的方法示例
2018/08/25 Python
python多进程使用及线程池的使用方法代码详解
2018/10/24 Python
Python爬虫实现HTTP网络请求多种实现方式
2020/06/19 Python
美国购买和销售礼品卡平台:Raise
2017/01/13 全球购物
DC Shoes荷兰官方网站:美国极限运动品牌
2019/10/22 全球购物
Java中有几种方法可以实现一个线程?用什么关键字修饰同步方法?stop()和suspend()方法为何不推荐使用?
2015/08/04 面试题
你所在的项目是如何确定版本号的
2015/12/28 面试题
设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。
2014/12/30 面试题
贷款担保申请书
2014/05/20 职场文书
房产协议书范本2014
2014/09/30 职场文书
2014年机关后勤工作总结
2014/12/16 职场文书
甲午大海战观后感
2015/06/02 职场文书