Prototype源碼淺析 String部分(二)
更新時間:2012年01月16日 00:15:28 作者:
本文接著上面的String部分,繼續(xù)下面表格的部分
格式 | camelize | capitalize | underscore | dasherize | inspect |
變形 | toArray | succ | times |
既然涉及到需要轉(zhuǎn)義的字符,我們自然要一份轉(zhuǎn)義字符信息,下面直接給出:
復(fù)制代碼 代碼如下:
String.specialChar = {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'\\': '\\\\'
}
【在JSON.js里面,多了一個'"',因為JSON里面string里面是不能出現(xiàn)"的,所以需要轉(zhuǎn)義】
第一步,當(dāng)然是要替換特殊的轉(zhuǎn)義字符,初始版本:
復(fù)制代碼 代碼如下:
function inspect() {
return this.replace(/[\b\t\n\f\r\\]/,function(a){
return String.specialChar[a];
});
}
對于JSON形式來說,雙引號是必須的,因此,我們應(yīng)該可以選擇自己的返回形式,所以,給inspect一個參數(shù)useDoubleQuotes,默認是用單引號返回字符串的。
復(fù)制代碼 代碼如下:
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, '\\\'') + "'";
}
現(xiàn)在這跟源碼中的功能差不多,不過Prototype源碼中的實現(xiàn)方式并不是這樣的,主要區(qū)別在于escapedString這一段。源碼中直接列出來所有的控制字符,表示為[\x00-\x1f],外加'\'就是[\x00-\x1f\\],因此改造上面的初始版本就是:
復(fù)制代碼 代碼如下:
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控制字符編碼表,對應(yīng)\x00-\x1f:
如果發(fā)現(xiàn)除了String.specialChar中的字符,還有其他的控制字符,源碼中也有一步處理,就是將控制字符轉(zhuǎn)變?yōu)閡nicode的表示形式,因為這個方法本身就是要獲得字符串的形式。
比如垂直制表符'\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])將當(dāng)前 Number 對象轉(zhuǎn)換為字符串,如果轉(zhuǎn)換后的字符串長度小于 length 指定的值,則用 0 在左邊補足其余的位數(shù)??蛇x的參數(shù) radix 用于指定轉(zhuǎn)換時所使用的進制。這是Prototype中Number的一個擴展,暫時知道即可。
因此'\v'.charCodeAt().toPaddedString(2, 16)就是將'\v'的字符編碼轉(zhuǎn)換成16進制的兩位編碼符[操作字符不會范圍有限制,因此不會超出],最后冠以'\u00'開頭即可。
方法說明:
toArray:將字符串拆分為字符數(shù)組。
succ:根據(jù) Unicode 字母表轉(zhuǎn)換字符串最后的字符為后續(xù)的字符
times:將字符串重復(fù)。
對應(yīng)具體的實現(xiàn)也很簡單,String部分的重要之處在于后面的腳本,JSON和替換處理,其他都是增強性質(zhì)的。
復(fù)制代碼 代碼如下:
function toArray() {
return this.split('');
}
其中split('')就將字符串打撒為單個字符,并以數(shù)組形式返回,如果還要再增強,可以給一個參數(shù)給toArray來指定分隔符。
復(fù)制代碼 代碼如下:
function toArray(pattern) {
return this.split(pattern);
}
console.log(toArray.call('my name is xesam',' '));//["my", "name", "is", "xesam"]
就是對split的使用而已,不過源碼中并沒有這么做,因為并沒有這個必要。
復(fù)制代碼 代碼如下:
function succ() {
return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
}
這里主要的就是fromCharCode和charCodeAt方法的使用。從代碼中也可以看出,兩者的明顯區(qū)別是fromCharCode是String的靜態(tài)方法,而charCodeAt是字符串的方法(掛在String.prototype上面)。然后兩者的作用正好相反,下面是http://www.w3school.com.cn給出的解釋:
fromCharCode() 可接受一個指定的 Unicode 值,然后返回一個字符串。
charCodeAt() 方法可返回指定位置的字符的 Unicode 編碼。這個返回值是 0 - 65535 之間的整數(shù)。
具體到succ,以字符串‘hello xesam'為例,先獲取除結(jié)尾字符外的所有字符‘hello xesa',然后加上Unicode表中‘m'后面的一個字符‘n',因此結(jié)果就是‘hello xesan'
以此為基礎(chǔ),我們要打印從‘a(chǎn)'到‘z'的所有字母,可以用以下的函數(shù):
復(fù)制代碼 代碼如下:
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');
復(fù)制代碼 代碼如下:
function times(count) {
return count < 1 ? '' : new Array(count + 1).join(this);
}
times作用是重復(fù)整個字符串,其主要思想就是將當(dāng)前字符作為數(shù)組的連接符調(diào)用join來獲得預(yù)期結(jié)果。當(dāng)然用循環(huán)添加也可以,不過沒這么簡潔。
如果要重復(fù)字符串里面的每個字符,可以用相同的思想:
復(fù)制代碼 代碼如下:
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這四個主要是關(guān)于變量名轉(zhuǎn)換的。
camelize : 將一個用橫線分隔的字符串轉(zhuǎn)換為 Camel 形式
capitalize :將一個字符串的首字母轉(zhuǎn)換為大寫,其它的字母全部轉(zhuǎn)為小寫。
underscore :將一個 Camel 形式的字符串轉(zhuǎn)換為以下劃線("_")分隔的一系列單詞。
dasherize :將字符串中的下劃線全部替換為橫線("_" 替換為 "-")。
最明顯的,可以用在CSS屬性與DOM的style屬性的相互轉(zhuǎn)換中【class與float不屬于此范疇】。對應(yīng)到上面的方法中,將CSS屬性轉(zhuǎn)換為對應(yīng)的DOM的style屬性可以使用camelize 方法,但是反過來卻沒有這個方法,因此必須連續(xù)調(diào)用underscore -> dasherize 方法才行。
復(fù)制代碼 代碼如下:
function camelize() {
return this.replace(/-+(.)?/g, function(match, chr) {
return chr ? chr.toUpperCase() : '';
});
}
核心是replace方法的使用,其他挺簡單,參見《淺析字符串的replace方法應(yīng)用》
復(fù)制代碼 代碼如下:
function capitalize() {
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
}
這里注意charAt(charAt() 方法可返回指定位置的字符。)與charCodeAt的區(qū)別就可以了。
復(fù)制代碼 代碼如下:
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();
}
實例來說明步驟:
復(fù)制代碼 代碼如下:
'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 形式的,就是得有‘峰'。
復(fù)制代碼 代碼如下:
function dasherize() {
return this.replace(/_/g, '-');
}
這個就是單純的字符替換而已。
來自小西山子
相關(guān)文章
使用prototype.js 的時候應(yīng)該特別注意的幾個問題.
使用prototype.js 的時候應(yīng)該特別注意的幾個問題....2007-04-04初學(xué)prototype,發(fā)個JS接受URL參數(shù)的代碼
初學(xué)prototype,發(fā)個JS接受URL參數(shù)的代碼...2007-02-02滾動經(jīng)典最新話題[prototype框架]下編寫
滾動經(jīng)典最新話題[prototype框架]下編寫...2006-10-10初學(xué)prototype,發(fā)個JS接受URL參數(shù)的代碼
初學(xué)prototype,發(fā)個JS接受URL參數(shù)的代碼...2006-09-09