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 相关文章推荐
Mootools 1.2教程 滚动条(Slider)
Sep 15 Javascript
Google排名中的10个最著名的 JavaScript库
Apr 27 Javascript
JavaScript面向对象设计二 构造函数模式
Dec 20 Javascript
JavaScript中的跨浏览器事件操作的基本方法整理
May 20 Javascript
详解AngularJs中$resource和restfu服务端数据交互
Sep 21 Javascript
jQuery给指定的table动态添加删除行的操作方法
Oct 12 Javascript
IE8利用自带的setCapture和releaseCapture解决iframe的拖拽事件方法
Oct 25 Javascript
整理一下常见的IE错误
Nov 18 Javascript
jQuery实现的简单手风琴效果示例
Aug 29 jQuery
Vue弹出菜单功能的实现代码
Sep 12 Javascript
JavaScript相等运算符的九条规则示例详解
Oct 20 Javascript
微信小程序点击滚动到指定位置的实现
May 22 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中使用socket方式GET、POST数据实例
2015/04/02 PHP
php 批量查询搜狗sogou代码分享
2015/05/17 PHP
Linux平台PHP5.4设置FPM线程数量的方法
2016/11/09 PHP
PHP计算近1年的所有月份
2017/03/13 PHP
[HTML/CSS/Javascript]WWTJS
2007/09/25 Javascript
javascript Array.remove() 数组删除
2009/08/06 Javascript
JavaScript DOM学习第六章 表单实例
2010/02/19 Javascript
JavaScript isArray()函数判断对象类型的种种方法
2010/10/11 Javascript
Javascript变量函数浅析
2011/09/02 Javascript
面向对象的Javascript之二(接口实现介绍)
2012/01/27 Javascript
javaScript arguments 对象使用介绍
2013/10/18 Javascript
使用js写的一个简易的投票
2013/11/27 Javascript
jquery统计输入文字的个数并对其进行判断
2014/01/07 Javascript
JavaScript学习笔记之Cookie对象
2015/01/22 Javascript
jquery append 动态添加的元素事件on 不起作用的解决方案
2015/07/30 Javascript
jquery密码强度校验
2015/12/02 Javascript
jQuery easyUI datagrid 增加求和统计行的实现代码
2016/06/01 Javascript
JavaScript数据存储 Cookie篇
2016/07/02 Javascript
Angular2中Bootstrap界面库ng-bootstrap详解
2016/10/18 Javascript
Vuex之理解state的用法实例
2017/04/19 Javascript
vue单页应用加百度统计代码(亲测有效)
2018/01/31 Javascript
npm全局模块卸载及默认安装目录修改方法
2018/05/15 Javascript
vue中监听返回键问题
2019/08/28 Javascript
javascript实现函数柯里化与反柯里化过程解析
2019/10/08 Javascript
vue-model实现简易计算器
2020/08/17 Javascript
TensorFlow实现AutoEncoder自编码器
2018/03/09 Python
python 实现判断ip连通性的方法总结
2018/04/22 Python
kaggle+mnist实现手写字体识别
2018/07/26 Python
python @propert装饰器使用方法原理解析
2019/12/25 Python
pyinstaller打包单文件时--uac-admin选项不起作用怎么办
2020/04/15 Python
用HTML5制作数字时钟的教程
2015/05/11 HTML / CSS
美国钻石商店:Zales
2016/11/20 全球购物
教师专业理论水平的自我评价分享
2013/11/09 职场文书
农村婚礼证婚词
2014/01/08 职场文书
探讨Java中的深浅拷贝问题
2021/06/26 Java/Android
抖音动画片,皮皮虾,《治愈系》动画在用这首REMIX作为背景音乐,Anak ,The last world with you完整版
2022/03/16 杂记