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控件的相对独立性
Sep 03 Javascript
关于jQuery中的end()使用方法
Jul 10 Javascript
textarea不能通过maxlength属性来限制字数的解决方法
Sep 01 Javascript
jQuery实现复选框成对选择及对应取消的方法
Mar 03 Javascript
jQuery插件EnPlaceholder实现输入框提示文字
Jun 05 Javascript
jquery中object对象循环遍历的方法
Dec 18 Javascript
Spring MVC中Ajax实现二级联动的简单实例
Jul 06 Javascript
浅谈js在html中的加载执行顺序,多个jquery ready执行顺序
Nov 26 Javascript
php 解压zip压缩包内容到指定目录的实例
Jan 23 Javascript
vue实现树形菜单效果
Mar 19 Javascript
微信小程序之事件交互操作实例分析
Dec 03 Javascript
vue基础之事件简写、事件对象、冒泡、默认行为、键盘事件实例分析
Mar 11 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实现根据词频生成tag云的方法
2015/04/17 PHP
Linux系统递归生成目录中文件的md5的方法
2015/06/29 PHP
WordPress开发中用于获取近期文章的PHP函数使用解析
2016/01/05 PHP
PHP 数组遍历foreach语法结构及实例
2016/06/13 PHP
thinkPHP简单导入和使用阿里云OSSsdk的方法
2017/03/15 PHP
PHP递归删除多维数组中的某个值
2017/04/17 PHP
PHP数据库编程之MySQL优化策略概述
2017/08/16 PHP
php swoft框架实例用法
2020/12/22 PHP
javascript 动态添加表格行
2006/06/22 Javascript
Javascript优化技巧(文件瘦身篇)
2008/01/28 Javascript
让JavaScript 轻松支持函数重载 (Part 1 - 设计)
2009/08/04 Javascript
javascript 自定义事件初探
2009/08/21 Javascript
基于javascript、ajax、memcache和PHP实现的简易在线聊天室
2015/02/03 Javascript
javascript获取当前的时间戳的方法汇总
2015/07/26 Javascript
jQuery实现手机上输入后隐藏键盘功能
2017/01/04 Javascript
javascript基础练习之翻转字符串与回文
2017/02/20 Javascript
ES6下React组件的写法示例代码
2017/05/04 Javascript
从零开始学习搭建React脚手架项目
2018/08/23 Javascript
详解React 服务端渲染方案完美的解决方案
2018/12/14 Javascript
详解Vue This$Store总结
2018/12/17 Javascript
详解JS判断页面是在手机端还是在PC端打开的方法
2019/04/26 Javascript
react-native滑动吸顶效果的实现过程
2019/06/03 Javascript
js实现日历
2020/11/07 Javascript
python统计文本文件内单词数量的方法
2015/05/30 Python
centos 安装python3.6环境并配置虚拟环境的详细教程
2018/02/22 Python
pandas 条件搜索返回列表的方法
2018/10/30 Python
python子线程退出及线程退出控制的代码
2019/10/16 Python
opencv python 图片读取与显示图片窗口未响应问题的解决
2020/04/24 Python
python框架flask入门之路由及简单实现方法
2020/06/07 Python
python线程优先级队列知识点总结
2021/02/28 Python
canvas 阴影和图形变换的示例代码
2018/01/02 HTML / CSS
期中考试后的反思
2014/02/08 职场文书
《小动物过冬》教学反思
2014/04/17 职场文书
冬季施工防火方案
2014/05/17 职场文书
销售行政专员岗位职责
2014/06/10 职场文书
MySQL解决Navicat设置默认字符串时的报错问题
2022/06/16 MySQL