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 相关文章推荐
js 数组操作代码集锦
Apr 28 Javascript
基于Jquery 解决Ajax请求的页面 浏览器后退前进功能,页面刷新功能实效问题
Dec 11 Javascript
获取客户端电脑日期时间js代码(jquery)
Sep 12 Javascript
js获得参数的getParameter使用示例
Feb 26 Javascript
深入理解JavaScript系列(47):对象创建模式(上篇)
Mar 04 Javascript
推荐10 个很棒的 jQuery 特效代码
Oct 04 Javascript
JavaScript编写页面半透明遮罩效果的简单示例
May 09 Javascript
IE8利用自带的setCapture和releaseCapture解决iframe的拖拽事件方法
Oct 25 Javascript
Vue学习笔记进阶篇之vue-router安装及使用方法
Jul 19 Javascript
jQuery EasyUI结合zTree树形结构制作web页面
Sep 01 jQuery
JavaScript设计模式之命令模式实例分析
Jan 16 Javascript
VScode格式化ESlint方法(最全最好用方法)
Sep 10 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中使用Oracle数据库(4)
2006/10/09 PHP
令PHP初学者头疼十四条问题大总结
2008/11/12 PHP
PHP中使用cURL实现Get和Post请求的方法
2013/03/13 PHP
PHP不用第三变量交换2个变量的值的解决方法
2013/06/02 PHP
PHP实现的方程求解示例分析
2016/11/11 PHP
php获取'/'传参的值简单方法
2017/07/13 PHP
Laravel 5+ .env环境配置文件详解
2020/04/06 PHP
DOM精简教程
2006/10/03 Javascript
js实现的跟随鼠标移动的时钟效果(中英文日期显示)
2011/01/17 Javascript
js中的cookie的读写操作示例详解
2014/04/17 Javascript
a标签click和href执行顺序探讨
2014/06/23 Javascript
nodejs开发微博实例
2015/03/25 NodeJs
jQuery中fadein与fadeout方法用法示例
2016/09/16 Javascript
jQuery实现边框动态效果的实例代码
2016/09/23 Javascript
jQuery:unbind方法的使用详解
2017/08/14 jQuery
详解Nuxt.js中使用Element-UI填坑
2019/09/06 Javascript
原生JS实现顶部导航栏显示按钮+搜索框功能
2019/12/25 Javascript
Python的SQLalchemy模块连接与操作MySQL的基础示例
2016/07/11 Python
Python实现的多线程同步与互斥锁功能示例
2017/11/30 Python
python写入已存在的excel数据实例
2018/05/03 Python
Python爬取商家联系电话以及各种数据的方法
2018/11/10 Python
selenium处理元素定位点击无效问题
2019/06/12 Python
python3+PyQt5 使用三种不同的简便项窗口部件显示数据的方法
2019/06/17 Python
python删除某个目录文件夹的方法
2020/05/26 Python
python制作抽奖程序代码详解
2021/01/15 Python
html5开发三八女王节表白神器
2018/03/07 HTML / CSS
钉钉企业内部H5微应用开发详解
2020/05/12 HTML / CSS
奥斯汀独木舟和皮划艇:Austin Canoe & Kayak
2018/05/22 全球购物
Charlotte Tilbury澳大利亚官网:英国美妆品牌
2018/10/05 全球购物
说一下mysql, oracle等常见数据库的分页实现方案
2012/09/29 面试题
行政专员岗位职责说明书
2014/07/30 职场文书
四风对照检查材料思想汇报
2014/09/20 职场文书
工商局领导班子存在的问题整改措施思想汇报
2014/10/05 职场文书
道士塔读书笔记
2015/06/30 职场文书
详解如何用Python实现感知器算法
2021/06/18 Python
Golang 实现WebSockets
2022/04/24 Golang