本文從一道簡單的字符串面試題開始,記錄字符串的一些方法,關注細節。
最近遇到一道面試題,覺得挺有意思,雖然簡單卻發人深省。題目大致如下:寫一個字符串轉成駝峰的方法,例.bottom.color->borderBottomColor。
操作字符串數組#
大部分人應該都能寫出這種方法,對字符串進行處理然後拼接成新的字符串。主要考察字符串的幾個 API,使用 charAt (n) 來取得字符串第 n 個下標的字符,也可以使用數組下標 ([]) 來取。
function tranformStr(str) {
var strArr = str.split(".");
for (var i = 1; i < strArr.length; i++) {
strArr[i] = strArr[i].charAt(0).toUpperCase() + strArr[i].substring(1);
}
return strArr.join("");
}
正則表達式#
第二種使用正則來解決,其實算是字符串的 replace 方法和正則的結合,難點主要還是在於 replace 方法的掌握。
function transformStr(str) {
var re = /\.(\w)/g;
return str.replace(re, function(match, p1) {
return p1.toUpperCase();
});
}
從以上兩種方法可以看出,使用正則的代碼量更少,但是對正則的理解和 replace 用法的要求也更高,下面總結一下 replace 這個字符串方法的一些 api。
replace 使用#
str.replace(regexp|substr, newSubStr|function)
replace 方法的第一個參數可以是一個正則或者字符串。
- regexp (pattern)
一個正則表達式(RegExp) 對象或者其字面量。該正則所匹配的內容會被第二個參數的返回值替換掉。
- substr (pattern)
一個要被 newSubStr 替換的字符串。其被視為一整個字符串,而不是一個正則表達式。僅僅是第一個匹配會被替換。
replace 方法的第二個參數可以是一個字符串或者函數。
- newSubStr (replacement)
用於替換掉第一個參數在原字符串中的匹配部分的字符串。該字符串中可以內插一些特殊的變量名。參考下面的使用字符串作為參數。
- function (replacement)
一個用來創建新子字符串的函數,該函數的返回值將替換掉第一個參數匹配到的結果。參考下面的指定一個函數作為參數。
replace 方法並不改變調用它的字符串本身,而只是返回一個新的替換後的字符串。
在進行全局的搜索替換時,正則表達式需包含 g 標誌。
使用字符串作為參數#
當第二個參數是字符串時,替換字符串可以插入下面的特殊變量名:
變量名 | 代表的值 |
---|---|
$$ | 插入一個 "$"。 |
$& | 插入匹配的子串。 |
$` | 插入當前匹配的子串左邊的內容。 |
$' | 插入當前匹配的子串右邊的內容。 |
$n | 假如第一個參數是 RegExp 對象,並且 n 是個小於 100 的非負整數,那麼插入第 n 個括號匹配的字符串。 |
下面是特殊變量名的具體使用:
"border.bottom.color".replace(/\.(\w)/g, "$$");
// border$ottom$olor
"border.bottom.color".replace(/\.(\w)/g, "$&");
// border.bottom.color
"border.bottom.color".replace(/\.(\w)/g, "$`");
// borderborderottomborder.bottomolor
"border.bottom.color".replace(/\.(\w)/g, "$1");
// borderbottomcolor
指定一個函數作為參數#
當第二個參數是一個函數時,在這種情況下,當匹配執行後, 该函數就會執行。 函數的返回值作為替換字符串。 (注意:上面提到的特殊替換參數在這裡不能被使用。) 另外要注意的是, 如果第一個參數是正則表達式, 並且其為全局匹配模式, 那麼這個方法將被多次調用, 每次匹配都會被調用。
變量名 | 代表的值 |
---|---|
match | 匹配的子串。(對應於上述的 $&。) |
p1,p2, ... | 假如 replace () 方法的第一個參數是一個 RegExp 對象,則代表第 n 個括號匹配的字符串。(對應於上述的 $1,$2 等。) |
offset | 匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是 “abcd”,匹配到的子字符串是 “bc”,那麼這個參數將是 1) |
string | 被匹配的原字符串。 |
注意:精確的參數個數依賴於 replace () 的第一個參數是否是一個正則表達式對象, 以及這個正則表達式中指定了多少個括號子串。
在文章最開始的題目中,我們需要匹配。後面跟著的第一個字母,並且將其替換為大寫字母。具體實現代碼如下:
function transformStr(str) {
var re = /\.(\w)/g;
return str.replace(re, function(match, p1) {
return p1.toUpperCase();
});
}
首先,聲明一個正則 re,匹配一個。後面跟著一個括號,這個括號稱為捕獲括號,匹配的內容會被記住以供第二個參數使用,捕獲括號內的 \w 匹配一個單字字符(字母、數字或者下劃線),等價於 [A-Za-z0-9]。第二個參數為函數,第一個字符串 match 是每次匹配到的字符串,在上述例子中就是.b 和.c,p1 則對應第一個括號匹配的字符串,對應 b 和 c,在函數內部對 p1 進行大寫轉換,因為 replace 產生的是一個全新的字符串,所以需要 return 出去。