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代码混淆综合解决方案-Javascript在线混淆器
Dec 18 Javascript
jquery使用ColorBox弹出图片组浏览层实例演示
Mar 14 Javascript
document.getElementBy("id")与$("#id")有什么区别
Sep 22 Javascript
js 浏览本地文件夹系统示例代码
Oct 24 Javascript
BAT及各大互联网公司2014前端笔试面试题--JavaScript篇
Oct 29 Javascript
浅析node.js中close事件
Nov 26 Javascript
JavaScript 节流函数 Throttle 详解
Jul 04 Javascript
javascript汉字拼音互转的简单实例
Oct 09 Javascript
Javascript中的神器——Promise
Feb 08 Javascript
基于IView中on-change属性的使用详解
Mar 15 Javascript
详解angularjs跨页面传参遇到的一些问题
Nov 01 Javascript
TypeScript 使用 Tuple Union 声明函数重载
Apr 07 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
综合图片计数器
2006/10/09 PHP
杏林同学录(八)
2006/10/09 PHP
什么是MVC,好东西啊
2007/05/03 PHP
PHPMyAdmin 快速配置方法
2009/05/11 PHP
php 伪静态之IIS篇
2014/06/02 PHP
ThinkPHP中自定义错误页面和提示页面实例
2014/11/22 PHP
详解thinkphp中的volist标签
2018/01/15 PHP
js 操作符实例代码
2009/10/24 Javascript
设置checkbox为只读(readOnly)的两种方式
2013/10/11 Javascript
javascript删除一个html元素节点的方法
2014/12/20 Javascript
jquery UI Datepicker时间控件的使用方法(加强版)
2015/11/07 Javascript
Js调用Java方法并互相传参的简单实例
2016/08/11 Javascript
js select实现省市区联动选择
2020/04/17 Javascript
jQuery实现手机上输入后隐藏键盘功能
2017/01/04 Javascript
详解vue-router 2.0 常用基础知识点之router-link
2017/05/10 Javascript
jQuery:unbind方法的使用详解
2017/08/14 jQuery
浅谈vue的iview列表table render函数设置DOM属性值的方法
2017/09/30 Javascript
nodejs实现截取上传视频中一帧作为预览图片
2017/12/10 NodeJs
vue-cli实现多页面多路由的示例代码
2018/01/30 Javascript
element-ui表格合并span-method的实现方法
2019/05/21 Javascript
通过js示例讲解时间复杂度与空间复杂度
2019/08/06 Javascript
tracking.js实现前端人脸识别功能
2020/04/16 Javascript
深入理解python中的select模块
2017/04/23 Python
解决Python获取字典dict中不存在的值时出错问题
2018/10/17 Python
Python寻找路径和查找文件路径的示例
2019/07/10 Python
python单线程下实现多个socket并发过程详解
2019/07/27 Python
基于Django框架的权限组件rbac实例讲解
2019/08/31 Python
Python爬虫实现“盗取”微信好友信息的方法分析
2019/09/16 Python
Django框架HttpRequest对象用法实例分析
2019/11/01 Python
基于django2.2连oracle11g解决版本冲突的问题
2020/07/02 Python
Python如何解除一个装饰器
2020/08/07 Python
Python爬虫模拟登陆哔哩哔哩(bilibili)并突破点选验证码功能
2020/12/21 Python
解决Firefox下不支持outerHTML问题代码分享
2014/06/04 HTML / CSS
路德维希•贝克(LUDWIG BECK)中文官网:德国大型美妆百货
2020/09/19 全球购物
大学生国庆节65周年演讲稿范文
2014/09/25 职场文书
工作迟到检讨书范文
2015/05/06 职场文书