Prototype源码浅析 String部分(一)之有关indexOf优化

添加到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的原理也是一样的。

(0)

相关推荐

  • Prototype源码浅析 String部分(二)

    格式 camelize | capitalize |  underscore |  dasherize  | inspect           变形 toArray |  succ  | times这里面一个有用的方法是inspect,按照参考手册的说明,他的作用是"返回该字符串针对调试的字符串表现形式(即用单引号或双引号包括起来,并使用 '\' 对特殊字符进行转义)",在Object的toJSON里面也涉及到这个方法. 既然涉及到需要转义的字符,我们自然要一份转义字符信息,下面直接

  • Prototype源码浅析 Number部分

    Number部分方法比较少,一共有8个: toColorPart: 将 Number 对象转换为具有两位数字的十六进制形式 succ: 返回当前 Number 对象的下一个值,即当前值加一 times: 采用 Ruby 的风格来封装一个标准的 [0...n] 循环 toPaddedString:将当前 Number 对象转换为字符串,如果转换后的字符串长度小于 length 指定的值,则用 0 在左边补足其余的位数 abs: 返回当前 Number 对象的绝对值. round: 返回当前 Num

  • Prototype源码浅析 String部分(四)之补充

    替换 interpolate  | sub |  scan |  truncate | gsubinterpolate : 将字符串看作一个模板,并使用 object 的属性填充它. sub : 将字符串中前指定个个与 pattern 指定的模式匹配的子串用 replacement 替换 scan : 遍历字符串中与参数 pattern 指定的模式匹配的所有子串.返回原始字符串本身. truncate : 将字符串截短为指定的长度(包含后缀部分), 并添加一个后缀. gsub :将字符串中所有与

  • Prototype源码浅析 String部分(三)之HTML字符串处理

    HTML处理 stripTags  | escapeHTML |  unescapeHTML     JSON处理 unfilterJSON |  isJSON |  evalJSON |  parseJSON 脚本处理 stripScripts |  extractScripts  | evalScripts现在,String部分转入具体的关联应用,分别对应 HTML字符串,JSON字符串和HTML中的脚本字符串. [乱入一句,有关JSON的一点东西,可以看看http://www.cnblog

  • Prototype源码浅析 String部分(一)之有关indexOf优化

    添加到String.prototype中的方法比较多,不过归结起来,大致分为下面几类: 分类 方法名  原始能力增强               strip |  include  |  startsWith  |  endsWith |  empty |  blank 格式 camelize | capitalize |  underscore |  dasherize  | inspect           变形 toArray |  succ  | times 替换 interpolat

  • Prototype源码浅析 Enumerable部分(二)

    前面each方法中掉了一个方面没有说,就是源码中的$break和$continue.这两个变量是预定义的,其作用相当于普通循环里面的break和continue语句的作用.出于效率的考虑,在某些操作中并不需要完全遍历一个集合(不局限于一个数组),所以break和continue还是很必要的. 对于一个循环来说,对比下面几种退出循环的方式: 复制代码 代码如下: var array_1 = [1,2,3]; var array_2 = ['a','b','c']; (function(){ for

  • Prototype源码浅析 Enumerable部分之each方法

    在javascript中,根本找不到Enumerable的影子,因为这一块是Prototype作者从Ruby中借鉴过来的.并且Enumerable在实际中根本没有直接应用的机会,都是混入到其他的对象中,可以说是其他对象的一个"父类"(不过只是调用了Object的extend方法,进行了方法的直接拷贝而已). 我并不熟悉Ruby,不过看Enumerable中的一些方法,倒是跟Python中的有几分相似. Enumerable其中一个最重要的方法是each,each这个方法应该都比较熟悉,

  • [转]prototype 源码解读 超强推荐第1/3页

    复制代码 代码如下: Prototype is a JavaScript framework that aims to ease development of dynamic web applications. Featuring a unique, easy-to-use toolkit for class-driven development and the nicest Ajax library around, Prototype is quickly becoming the codeb

  • Ajax::prototype 源码解读

    AJAX之旅(1):由prototype_1.3.1进入javascript殿堂-类的初探  还是决定冠上ajax的头衔,毕竟很多人会用这个关键词搜索.虽然我认为这只是个炒作的概念,不过不得不承认ajax叫起来要方便多了.所以ajax的意思我就不详细解释了. 写这个教程的起因很简单:经过一段时间的ajax学习,有一些体会,并且越发认识到ajax技术的强大,所以决定记录下来,顺便也是对自己思路的整理.有关这个教程的后续,请关注http://www.x2design.net 前几年,javascri

  • java String源码和String常量池的全面解析

    1. String 介绍,常用方法源码分析 2. String 常量池分析 常用方法 equals trim replace concat split startsWith 和 endsWith substring toUpperCase() 和 toLowerCase() compareTo String 介绍 String类被final所修饰,也就是说String对象是不可变量,并发程序最喜欢不可变量了.String类实现了Serializable, Comparable, CharSequ

随机推荐