Prototype源码浅析 String部分(二)


Posted in Javascript onJanuary 16, 2012
格式 camelize | capitalize |  underscore |  dasherize  | inspect          
变形 toArray |  succ  | times
这里面一个有用的方法是inspect,按照参考手册的说明,他的作用是“返回该字符串针对调试的字符串表现形式(即用单引号或双引号包括起来,并使用 '\' 对特殊字符进行转义)”,在Object的toJSON里面也涉及到这个方法。

既然涉及到需要转义的字符,我们自然要一份转义字符信息,下面直接给出:

String.specialChar = { 
'\b': '\\b', 
'\t': '\\t', 
'\n': '\\n', 
'\f': '\\f', 
'\r': '\\r', 
'\\': '\\\\' 
}

【在JSON.js里面,多了一个'"',因为JSON里面string里面是不能出现"的,所以需要转义】

第一步,当然是要替换特殊的转义字符,初始版本:

function inspect() { 
return this.replace(/[\b\t\n\f\r\\]/,function(a){ 
return String.specialChar[a]; 
}); 
}

对于JSON形式来说,双引号是必须的,因此,我们应该可以选择自己的返回形式,所以,给inspect一个参数useDoubleQuotes,默认是用单引号返回字符串的。

function inspect(useDoubleQuotes) { 
var escapedString = this.replace(/[\b\t\n\f\r\\]/,function(a){ 
return String.specialChar[a]; 
}); 
if (useDoubleQuotes){ 
return '"' + escapedString.replace(/"/g, '\\"') + '"'; 
} 
return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 
}

现在这跟源码中的功能差不多,不过Prototype源码中的实现方式并不是这样的,主要区别在于escapedString这一段。源码中直接列出来所有的控制字符,表示为[\x00-\x1f],外加'\'就是[\x00-\x1f\\],因此改造上面的初始版本就是:

function inspect(useDoubleQuotes) { 
var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { 
if (character in String.specialChar) { 
return String.specialChar[character]; 
} 
return character ; 
}); 
if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; 
return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 
} 
[html] 
附,ASCII控制字符编码表,对应\x00-\x1f: 


如果发现除了String.specialChar中的字符,还有其他的控制字符,源码中也有一步处理,就是将控制字符转变为unicode的表示形式,因为这个方法本身就是要获得字符串的形式。 
比如垂直制表符'\v'。'\v'.inspect() -->'\u000b' 
完整版本: 
[code] 
function inspect(useDoubleQuotes) { 
var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { 
if (character in String.specialChar) { 
return String.specialChar[character]; 
} 
return '\\u00' + character.charCodeAt().toPaddedString(2, 16); 
}); 
if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; 
return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 
}

其中toPaddedString(length[, radix])将当前 Number 对象转换为字符串,如果转换后的字符串长度小于 length 指定的值,则用 0 在左边补足其余的位数。可选的参数 radix 用于指定转换时所使用的进制。这是Prototype中Number的一个扩展,暂时知道即可。

因此'\v'.charCodeAt().toPaddedString(2, 16)就是将'\v'的字符编码转换成16进制的两位编码符[操作字符不会范围有限制,因此不会超出],最后冠以'\u00'开头即可。

方法说明:
toArray:将字符串拆分为字符数组。
succ:根据 Unicode 字母表转换字符串最后的字符为后续的字符
times:将字符串重复。

对应具体的实现也很简单,String部分的重要之处在于后面的脚本,JSON和替换处理,其他都是增强性质的。

function toArray() { 
return this.split(''); 
}

其中split('')就将字符串打撒为单个字符,并以数组形式返回,如果还要再增强,可以给一个参数给toArray来指定分隔符。

function toArray(pattern) { 
return this.split(pattern); 
} 
console.log(toArray.call('my name is xesam',' '));//["my", "name", "is", "xesam"]

就是对split的使用而已,不过源码中并没有这么做,因为并没有这个必要。
function succ() { 
return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); 
}

这里主要的就是fromCharCode和charCodeAt方法的使用。从代码中也可以看出,两者的明显区别是fromCharCode是String的静态方法,而charCodeAt是字符串的方法(挂在String.prototype上面)。然后两者的作用正好相反,下面是http://www.w3school.com.cn给出的解释:

fromCharCode() 可接受一个指定的 Unicode 值,然后返回一个字符串。

charCodeAt() 方法可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数。

具体到succ,以字符串‘hello xesam'为例,先获取除结尾字符外的所有字符‘hello xesa',然后加上Unicode表中‘m'后面的一个字符‘n',因此结果就是‘hello xesan'
以此为基础,我们要打印从‘a'到‘z'的所有字母,可以用以下的函数:

function printChar(start,end){ 
var s = (start + '').charCodeAt() 
var e = (end + '').charCodeAt(); 
if(s > e){ 
s = [e,e=s][0]; 
} 
for(var i = s ;i <= e; i++){ 
console.log(String.fromCharCode(i)); 
} 
} 
printChar('a','z');

function times(count) { 
return count < 1 ? '' : new Array(count + 1).join(this); 
}

times作用是重复整个字符串,其主要思想就是将当前字符作为数组的连接符调用join来获得预期结果。当然用循环添加也可以,不过没这么简洁。
如果要重复字符串里面的每个字符,可以用相同的思想:

String.prototype.letterTimes = function(count){ 
var arr = []; 
arr.length = count + 1; 
return this.replace(/\w/g,function(a){ 
return arr.join(a); 
}) 
} 
console.log('xesam'.letterTimes(3));//xxxeeesssaaammm

camelize | capitalize | underscore | dasherize这四个主要是关于变量名转换的。
camelize : 将一个用横线分隔的字符串转换为 Camel 形式
capitalize :将一个字符串的首字母转换为大写,其它的字母全部转为小写。
underscore :将一个 Camel 形式的字符串转换为以下划线("_")分隔的一系列单词。
dasherize :将字符串中的下划线全部替换为横线("_" 替换为 "-")。

最明显的,可以用在CSS属性与DOM的style属性的相互转换中【class与float不属于此范畴】。对应到上面的方法中,将CSS属性转换为对应的DOM的style属性可以使用camelize 方法,但是反过来却没有这个方法,因此必须连续调用underscore -> dasherize 方法才行。

function camelize() { 
return this.replace(/-+(.)?/g, function(match, chr) { 
return chr ? chr.toUpperCase() : ''; 
}); 
}

核心是replace方法的使用,其他挺简单,参见《浅析字符串的replace方法应用》

function capitalize() { 
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 
}

这里注意charAt(charAt() 方法可返回指定位置的字符。)与charCodeAt的区别就可以了。

function underscore() { 
return this.replace(/::/g, '/') 
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') 
.replace(/([a-z\d])([A-Z])/g, '$1_$2') 
.replace(/-/g, '_') 
.toLowerCase(); 
}

实例来说明步骤:
'helloWorld::ABCDefg'.underscore() 
//'helloWorld::ABCDefg' 
.replace(/::/g, '/') //'helloWorld/ABCDefg' 
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')//helloWorld/ABC_Defg 
.replace(/([a-z\d])([A-Z])/g, '$1_$2') //hello_World/ABC_Defg 
.replace(/-/g, '_') //hello_World/ABC_Defg 
.toLowerCase(); //hello_world/abc_defg

这个方法只适合Camel 形式的,就是得有‘峰'。
function dasherize() { 
return this.replace(/_/g, '-'); 
}

这个就是单纯的字符替换而已。
来自小西山子
Javascript 相关文章推荐
Prototype 1.5.0_rc1 及 Prototype 1.5.0 Pre0小抄本
Sep 22 Javascript
基于jquery点击自以外任意处,关闭自身的代码
Feb 10 Javascript
最佳6款用于移动网站开发的jQuery 图片滑块插件小结
Jul 20 Javascript
Javascript对象中关于setTimeout和setInterval的this介绍
Jul 21 Javascript
js 点击页面其他地方关闭弹出层(示例代码)
Dec 24 Javascript
jquery实现相册一下滑动两次的方法
Feb 09 Javascript
javascript计算对象长度的方法
Oct 25 Javascript
vue 弹框产生的滚动穿透问题的解决
Sep 21 Javascript
如何优雅的在一台vps(云主机)上面部署vue+mongodb+express项目
Jan 20 Javascript
javascript移动端 电子书 翻页效果实现代码
Sep 07 Javascript
JS 设计模式之:工厂模式定义与实现方法浅析
May 06 Javascript
Taro小程序自定义顶部导航栏功能的实现
Dec 17 Javascript
深入理解JavaScript系列(11) 执行上下文(Execution Contexts)
Jan 15 #Javascript
深入理解JavaScript系列(10) JavaScript核心(晋级高手必读篇)
Jan 15 #Javascript
深入理解JavaScript系列(9) 根本没有“JSON对象”这回事!
Jan 15 #Javascript
深入理解JavaScript系列(8) S.O.L.I.D五大原则之里氏替换原则LSP
Jan 15 #Javascript
深入理解JavaScript系列(7) S.O.L.I.D五大原则之开闭原则OCP
Jan 15 #Javascript
深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP
Jan 15 #Javascript
深入理解JavaScript系列(6) 强大的原型和原型链
Jan 15 #Javascript
You might like
用定制的PHP应用程序来获取Web服务器的状态信息
2006/10/09 PHP
Javascript与PHP验证用户输入URL地址是否正确
2014/10/09 PHP
ecshop适应在PHP7的修改方法解决报错的实现
2016/11/01 PHP
JS IE和FF兼容性问题汇总
2009/02/09 Javascript
javascript parseInt() 函数的进制转换注意细节
2013/01/08 Javascript
JQuery入门——事件切换之toggle()方法应用介绍
2013/02/05 Javascript
Javascript中String的常用方法实例分析
2015/06/13 Javascript
jQuery实现指定内容滚动同时左侧或其它地方不滚动的方法
2015/08/08 Javascript
基于insertBefore制作简单的循环插空效果
2015/09/21 Javascript
json对象转为字符串,当做参数传递时加密解密的实现方法
2016/06/29 Javascript
详解node.js搭建代理服务器请求数据
2017/04/08 Javascript
bootstrap中日历范围选择插件daterangepicker的使用详解
2018/04/17 Javascript
如何手动实现es5中的bind方法详解
2018/12/07 Javascript
js实现全选反选不选功能代码详解
2019/04/24 Javascript
nuxt踩坑之Vuex状态树的模块方式使用详解
2019/09/06 Javascript
json_decode 索引为数字时自动排序问题解决方法
2020/03/28 Javascript
浅谈JS for循环中使用break和continue的区别
2020/07/21 Javascript
Python入门篇之面向对象
2014/10/20 Python
Python模块结构与布局操作方法实例分析
2017/07/24 Python
opencv改变imshow窗口大小,窗口位置的方法
2018/04/02 Python
使用Python来做一个屏幕录制工具的操作代码
2020/01/18 Python
python绘制玫瑰的实现代码
2020/03/02 Python
Tensorflow tf.nn.atrous_conv2d如何实现空洞卷积的
2020/04/20 Python
HTML5操作WebSQL数据库的实例代码
2017/08/26 HTML / CSS
Myprotein蛋白粉美国官网:欧洲畅销运动营养品牌
2016/11/15 全球购物
加拿大消费电子和手机购物网站:The Source
2017/01/28 全球购物
Diptyque英国官方网站:源自法国的知名香氛品牌
2019/08/28 全球购物
方正Java笔试题
2014/07/03 面试题
计算机软件个人的自荐信范文
2013/12/01 职场文书
教师一岗双责责任书
2014/04/16 职场文书
小学模范班主任事迹材料
2014/05/13 职场文书
党员自我评议对照检查材料
2014/09/27 职场文书
捐资助学感谢信
2015/01/21 职场文书
自主招生自荐信格式范文
2015/03/25 职场文书
升学宴家长致辞
2015/07/27 职场文书
Python面向对象之成员相关知识总结
2021/06/24 Python