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中的16进制字符(改进)
Nov 21 Javascript
详解JavaScript语法对{}处理的坑爹之处
Jun 05 Javascript
禁止按回车键提交表单的方法
Jun 11 Javascript
详解JavaScript树结构
Jan 09 Javascript
JS匹配日期和时间的正则表达式示例
May 12 Javascript
AngularJS自定义指令之复制指令实现方法
May 18 Javascript
教你用Cordova打包Vue项目的方法
Oct 17 Javascript
浅谈在vue中用webpack打包之后运行文件的问题以及相关配置方法
Feb 21 Javascript
node.js之基础加密算法模块crypto详解
Sep 11 Javascript
解决vue watch数据的方法被调用了两次的问题
Nov 07 Javascript
详解如何解决使用JSON.stringify时遇到的循环引用问题
Mar 23 Javascript
react中的DOM操作实现
Jun 30 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的魔术方法__get()和__set()使用介绍
2012/09/19 PHP
Laravel学习教程之本地化模块
2017/08/18 PHP
kindeditor 加入七牛云上传的实例讲解
2017/11/12 PHP
不用MOUSEMOVE也能滑动啊
2007/05/23 Javascript
node.js chat程序如何实现Ajax long-polling长链接刷新模式
2012/03/13 Javascript
js获取通过ajax返回的map型的JSONArray的方法
2014/01/09 Javascript
JavaScript修改浏览器tab标题小技巧
2015/01/06 Javascript
JavaScript中Null与Undefined的区别解析
2015/06/30 Javascript
基于javascript数组实现图片轮播
2016/05/02 Javascript
jQuery数据检索中根据关键字快速定位GridView指定行的实现方法
2016/06/08 Javascript
JavaScript登录验证码的实现
2016/10/27 Javascript
基于JavaScript实现Tab选项卡切换效果
2016/11/24 Javascript
AngularJS入门示例之Hello World详解
2017/01/04 Javascript
微信小程序 基础知识css样式media标签
2017/02/15 Javascript
gulp加批处理(.bat)实现ng多应用一键自动化构建
2017/02/16 Javascript
js实现导航吸顶效果
2017/02/24 Javascript
Node.js使用Express创建Web项目详细教程
2017/03/31 Javascript
javascript异常处理实现原理详解
2020/02/17 Javascript
实现vuex原理的示例
2020/10/21 Javascript
python中Flask框架简单入门实例
2015/03/21 Python
Python编程实现二叉树及七种遍历方法详解
2017/06/02 Python
Python升级导致yum、pip报错的解决方法
2017/09/06 Python
基于Python代码编辑器的选用(详解)
2017/09/13 Python
tensorflow 限制显存大小的实现
2020/02/03 Python
CSS3五个技巧给你的网站带来出色的效果
2009/04/02 HTML / CSS
Html5中的桌面通知Notification的实现
2018/09/25 HTML / CSS
俄罗斯香水在线商店:AromaCode
2019/12/04 全球购物
华硕新加坡官方网上商店:ASUS Singapore
2020/07/09 全球购物
优秀学生干部推荐材料
2014/02/03 职场文书
管理岗位竞聘演讲稿
2014/08/18 职场文书
刑事申诉状范文
2015/05/20 职场文书
欠条格式范本
2015/07/03 职场文书
优秀党员先进事迹材料2016
2016/02/29 职场文书
如何拟写通知正文?
2019/04/02 职场文书
基于go interface{}==nil 的几种坑及原理分析
2021/04/24 Golang
table设置超出部分隐藏,鼠标移上去显示全部内容的方法
2022/12/24 HTML / CSS