JavaScript 字串操作(Strings)——深入了解 substring、slice、split、replace、match 等方法
簡介
在前端開發或 Node.js 後端程式中,字串是最常見的資料型別之一。無論是處理使用者輸入、解析 API 回傳的 JSON、或是動態產生 HTML,字串的操作能力直接影響程式的可讀性與效能。
JavaScript 為字串提供了多樣且功能強大的內建方法,最常被使用的包括 substring()、slice()、split()、replace()、match() 等。掌握這些方法不僅能讓你寫出更簡潔的程式碼,還能避免常見的錯誤與效能瓶頸。
本篇文章將以 繁體中文(台灣) 為基礎,從概念說明到實作範例,逐步帶你了解每個方法的使用時機、注意事項與最佳實踐,適合剛入門的初學者以及想要深化字串處理技巧的中級開發者。
核心概念
1. substring(start, end)
- 功能:從字串的
start位置(含)截取到end位置(不含),若省略end則截取到字串結尾。 - 特性:負數會被視為
0,且如果start > end,會自動交換兩個參數的值。
// 範例 1:基本用法
let text = "JavaScript 教學課程";
let part = text.substring(0, 10); // "JavaScript"
console.log(part);
// 範例 2:省略 end
let tail = text.substring(11); // "教學課程"
console.log(tail);
// 範例 3:參數順序會自動調整
let swapped = text.substring(10, 0); // 同上,結果為 "JavaScript"
console.log(swapped);
⚠️ 陷阱:
substring會把負數視為0,若你真的需要支援負索引,請改用slice。
2. slice(beginIndex, endIndex)
- 功能:類似
substring,但支援負數索引(從字串尾端算起)。 - 特性:
beginIndex為負數時,等於str.length + beginIndex。
// 範例 4:使用負數索引
let url = "https://example.com/page?id=123";
let query = url.slice(-9); // "id=123"
console.log(query);
// 範例 5:結合正負數
let domain = url.slice(8, -5); // "example.com/page"
console.log(domain);
⚠️ 陷阱:
slice不會自動交換 參數順序,若beginIndex > endIndex會回傳空字串。
3. split(separator, limit)
- 功能:將字串依照指定的分隔符切割成陣列。
- 參數:
separator:字串或正規表達式。limit(可選):限制回傳陣列的長度。
// 範例 6:基本分割
let csv = "蘋果,香蕉,芒果,葡萄";
let fruits = csv.split(","); // ["蘋果","香蕉","芒果","葡萄"]
console.log(fruits);
// 範例 7:使用正規表達式分割
let sentence = "JavaScript是最棒的語言!";
let words = sentence.split(/\W+/); // ["JavaScript","是","最棒","的","語言",""]
console.log(words);
// 範例 8:限制結果長度
let limited = csv.split(",", 2); // ["蘋果","香蕉"]
console.log(limited);
⚠️ 陷阱:若
separator為空字串 (""),split會把每個字元都拆開,可能會產生巨大的陣列,務必留意記憶體使用。
4. replace(searchValue, replaceValue)
- 功能:將字串中第一個符合
searchValue的子字串取代為replaceValue。 - 支援:
searchValue可以是字串或正規表達式;若使用全局 (/g) 修飾符,則會一次取代全部。
// 範例 9:字串取代(只會替換第一個)
let msg = "今天是星期五,星期五很開心!";
let newMsg = msg.replace("星期五", "星期六");
console.log(newMsg); // "今天是星期六,星期五很開心!"
// 範例 10:使用正規表達式全局取代
let allMsg = msg.replace(/星期五/g, "星期六");
console.log(allMsg); // "今天是星期六,星期六很開心!"
// 範例 11:使用函式動態產生取代文字
let template = "使用者: {user}, 日期: {date}";
let result = template.replace(/\{(\w+)\}/g, (_, key) => {
const map = { user: "Alice", date: "2025/11/19" };
return map[key];
});
console.log(result); // "使用者: Alice, 日期: 2025/11/19"
⚠️ 陷阱:若
searchValue為字串,replace只會取代第一個出現 的子字串。想一次全部取代,請使用正規表達式加上g標誌。
5. match(regexp)
- 功能:將字串與正規表達式比對,回傳符合結果的陣列(含捕獲群組),或
null。 - 注意:若正規表達式未加上
g,回傳的陣列會包含捕獲群組與index、input等屬性;加上g時,只回傳所有匹配結果(不含捕獲群組)。
// 範例 12:取得所有電話號碼(全局)
let phones = "連絡電話:02-1234-5678、0912-345-678、(03)8765-4321".match(/\d{2,4}[-]?\d{3,4}[-]?\d{4}/g);
console.log(phones); // ["02-1234-5678","0912-345-678","03)8765-4321"]
// 範例 13:捕獲群組(不使用 g)
let dateStr = "2025-11-19";
let parts = dateStr.match(/(\d{4})-(\d{2})-(\d{2})/);
console.log(parts[0]); // "2025-11-19"
console.log(parts[1]); // "2025"
console.log(parts[2]); // "11"
console.log(parts[3]); // "19"
// 範例 14:使用 matchAll(ES2020)取得多筆捕獲
let text2 = "apple:5, banana:12, cherry:7";
let iter = text2.matchAll(/(\w+):(\d+)/g);
for (const m of iter) {
console.log(`水果 ${m[1]} 數量 ${m[2]}`);
}
⚠️ 陷阱:
match若找不到匹配會回傳null,直接取索引會拋出錯誤,務必先檢查結果是否為null。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 解決方式 |
|---|---|---|
負數索引在 substring 無效 |
substring(-2, 3) 會被視為 substring(0, 3) |
使用 slice 或自行處理負數 |
replace 只替換第一個 |
字串作為搜尋值時不會全局取代 | 改用正規表達式 /pattern/g |
split("") 產生巨量陣列 |
每個字元分割會佔用大量記憶體 | 僅在必要時使用,或改用迭代方式 |
match 返回 null |
未匹配時直接解構會拋錯 | `const result = str.match(reg) |
正則表達式的 g 與捕獲群組衝突 |
加 g 後 match 不會返回捕獲群組 |
使用 matchAll 或去掉 g 取得單筆結果 |
最佳實踐建議
- 選擇最適合的方法:若需要負數索引,優先使用
slice;若只想截取一次且不在乎負數,substring更直觀。 - 正則表達式的寫法要明確:使用
\b、^、$等錨點,避免意外匹配。 - 避免不必要的字串拼接:在大量字串組合時,使用模板字面量 (
`...${}`) 或Array.join()效能較佳。 - 記憶體與效能:對於長字串或大量資料,盡量使用一次性操作(如
replace搭配正則)而非多次split+join。
實際應用場景
1. 表單驗證
function isEmail(str) {
// 使用 match 搭配簡易 Email 正則
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(str);
}
console.log(isEmail("test@example.com")); // true
2. URL 參數解析
function getQueryParams(url) {
const queryString = url.split("?")[1] || "";
return queryString.split("&").reduce((obj, pair) => {
const [key, value] = pair.split("=");
if (key) obj[decodeURIComponent(key)] = decodeURIComponent(value);
return obj;
}, {});
}
const params = getQueryParams("https://site.com/page?uid=42&lang=zh-tw");
console.log(params); // { uid: "42", lang: "zh-tw" }
3. 動態產生多語系文字
const i18n = {
en: { welcome: "Welcome, {name}!" },
tw: { welcome: "歡迎,{name}!" }
};
function t(lang, key, vars) {
const tmpl = i18n[lang][key];
return tmpl.replace(/\{(\w+)\}/g, (_, k) => vars[k] ?? "");
}
console.log(t("tw", "welcome", { name: "小明" })); // 歡迎,小明!
4. 日誌檔案分析
const log = `
[2025-11-18 10:00] INFO User login: alice
[2025-11-18 10:05] ERROR Failed to load resource
[2025-11-19 09:30] WARN Disk space low
`;
const errors = [...log.matchAll(/\[([\d-]+\s[\d:]+)\]\sERROR\s(.+)/g)];
errors.forEach(([_, time, msg]) => {
console.log(`時間: ${time} | 錯誤訊息: ${msg}`);
});
總結
字串操作是 JavaScript 開發中不可或缺的基礎技能。透過本篇文章,我們:
- 了解了
substring、slice、split、replace、match五大核心方法的差異與適用情境。 - 透過 5 個以上的實務範例,看到每個方法在真實專案中的具體應用。
- 探討了常見的陷阱,並提供 最佳實踐,幫助你寫出更安全、效能更佳的程式碼。
- 以表單驗證、URL 解析、多語系文字、日誌分析等 實際場景,展示字串方法如何解決日常開發問題。
掌握這些字串技巧後,你將能更自信地處理文字資料,減少 bug 的產生,同時提升程式的可維護性與執行效能。未來若需要更進階的文字處理(例如 Unicode 正規化、字元寬度計算),不妨再深入探索 String.prototype.normalize、Intl 以及第三方函式庫(如 lodash、moment)。祝你在 JavaScript 的字串世界裡玩得開心、寫得順手! 🚀