JavaScript ES6新增字符串方法详解:includes、padStart等
深入解析现代 JavaScript (ES6 / ES2017) 新增的核心字符串方法,包括 includes、startsWith、endsWith、repeat、padStart 与 padEnd 的语法规则、执行流程、底层机制与实战避坑技巧。
在 ECMAScript 2015(ES6)及后续规范发布之前,JavaScript 开发者进行字符串子串检索几乎完全依赖 indexOf,进行数字补零与定宽对齐则依赖繁重的自定义循环或三元表达式。现代 ECMAScript 规范针对这些高频操作推出了 includes、startsWith、endsWith、repeat 以及 padStart、padEnd 等原生 API,通过明确的语义定义和经过引擎级内联优化的执行效率,从根本上消除了以往代码冗长、边界易错的问题。本文将逐一拆解这些方法的调用语法、参数行为、内部运作流程与典型实践场景。
一、现代字符串方法体系与规范归属
在理解具体方法前,需要厘清它们的语言规范演进。虽然开发者通常习惯将现代前端中新增的字符串方法通称为“ES6 字符串新特性”,但在标准归属上存在明确划分:
- ECMAScript 2015 (ES6):引入了用于模式检索的
includes()、startsWith()、endsWith(),以及用于快速生成重复序列的repeat()。此外还规范了用于 Unicode 码点处理的codePointAt()和String.fromCodePoint()。 - ECMAScript 2017 (ES8):正式补充了字符串定宽填充方法
padStart()与padEnd()。它们彻底标准化了长期存在于社区实用库中的字符串对齐逻辑。
这些新方法的共同设计哲学是语义明确化与操作不可变性:所有方法均不改变原始字符串,而是直接返回全新的运算结果或清晰的布尔值。
二、子串检索三剑客:includes、startsWith、endsWith
在过去,判断字符串是否包含子串的标准写法是 str.indexOf('foo') !== -1。这种方式不仅可读性差,而且在配合条件判断时极易踩坑——例如当匹配字符恰好位于开头第 0 位时,indexOf 返回 0,如果误写成 if (str.indexOf('foo')) 就会因 0 被隐式转换为 false 而触发严重逻辑漏洞。ES6 引入的检索三剑客直接返回严格的布尔值。
1. includes:全局切片包含检测
str.includes(searchString[, position]) 用于判定原始字符串中是否包含指定的子串。第二个参数 position 可选,表示从哪一索引开始向后检索,默认值为 0。
const url = "https://api.example.com/v1/users";
// 基础包含检测:直接获取布尔值
const isApi = url.includes("api"); // true
const hasAuth = url.includes("auth"); // false
// 指定检索起始位置(跳过前面的协议部分)
const hasApiAfter10 = url.includes("api", 10); // false (api 出现于索引 8)
2. startsWith:前缀头部匹配
str.startsWith(searchString[, position]) 用于判断字符串是否以目标子串开头。参数 position 表示开始比对的索引位置,默认值为 0。
const path = "/assets/images/logo.png";
// 检测是否以绝对路径斜杠开头
const isAbsolute = path.startsWith("/"); // true
// 从指定索引处验证前缀(跳过 /assets)
const isImages = path.startsWith("images", 8); // true (索引 8 处正好为 "images")
3. endsWith:后缀尾部匹配(注意参数含义)
str.endsWith(searchString[, endPosition]) 用于判断字符串是否以目标子串结尾。特别需要注意:其第二个参数是 endPosition(截断长度),而非起始索引。如果传入 endPosition,检索范围将被限定为 str.slice(0, endPosition),其默认值为 str.length。
const fileName = "report-2026.final.pdf";
// 检测文件扩展名
const isPdf = fileName.endsWith(".pdf"); // true
// 限定前 11 个字符范围 ("report-2026"),检测其结尾
const isYear2026 = fileName.endsWith("2026", 11); // true
避坑提醒:includes、startsWith、endsWith 均严格区分大小写。此外,传入非字符串参数时(例如 null 或 undefined),JavaScript 会隐式调用 ToString() 将其转换为字符串 "null" 或 "undefined" 进行匹配,开发中应格外注意类型安全。
三、模式生成利器:repeat
str.repeat(count) 将原字符串重复拼接 count 次并返回新的字符串。该方法消除了以往为了重复字符而不得不使用 new Array(count + 1).join(str) 这种别扭且损耗性能的 Hack 手法。
// 1. 打印控制台分割线
const divider = "=".repeat(20);
console.log(divider); // "===================="
// 2. 构建多层级目录树或缩进
function getIndent(depth) {
return " ".repeat(depth);
}
console.log(getIndent(3) + "└── 子节点文件"); // " └── 子节点文件"
// 3. 生成密码隐藏占位符
const mask = "*".repeat(6); // "******"
repeat 的边界与异常规则
- 参数为 0:返回空字符串
""。 - 参数为浮点数:会自动调用内部抽象操作向下取整,例如
"abc".repeat(2.9)等价于"abc".repeat(2)。 - 负数与无穷大:若
count < 0或count === Infinity,直接抛出RangeError。
四、定宽填充与格式对齐:padStart 与 padEnd
在日常业务开发中,格式化字符串非常频繁,例如日期补零(将 5 格式化为 05)、银行卡号脱敏展示(保留后四位其余前置补 *)、以及命令行打印表格文本的左右对齐。ES2017 规范正式引入了 padStart() 和 padEnd(),彻底终结了繁琐的手工填充逻辑。
1. 语法与参数解析
两个方法的签名一致:
str.padStart(targetLength[, padString]):向字符串头部填充字符,直到总长度达到targetLength。str.padEnd(targetLength[, padString]):向字符串尾部填充字符,直到总长度达到targetLength。
参数说明:
targetLength:填充后的目标长度。如果原字符串本身长度已经大于或等于targetLength,则直接原样返回原字符串,绝对不会发生反向截断。padString:用于填充的模板字符串。可选参数,默认值为单个空格" "。若填充字符串较长超出所需长度,超出部分将被自动截断舍弃。
2. 实战应用示例
// 场景 1:标准时间与日期补零(极高频)
const now = new Date();
const month = String(now.getMonth() + 1).padStart(2, "0");
const day = String(now.getDate()).padStart(2, "0");
const formattedDate = `${now.getFullYear()}-${month}-${day}`;
// 输出如 "2026-03-09"
// 场景 2:数据脱敏与掩码
const rawCard = "6222021234567890";
const lastFour = rawCard.slice(-4);
const maskedCard = lastFour.padStart(rawCard.length, "*");
console.log(maskedCard); // "************7890"
// 场景 3:十六进制颜色补足
const hexValue = (255).toString(16).padStart(6, "0");
console.log("#" + hexValue); // "#0000ff"
// 场景 4:控制台表格列右对齐 (padEnd)
const items = [
{ name: "Apple", price: "$1.20" },
{ name: "Watermelon", price: "$15.00" },
];
items.forEach(item => {
// 将名称列固定占位 14 个字符,右侧留空
console.log(item.name.padEnd(14, " ") + item.price);
});
// 输出对齐结果:
// Apple $1.20
// Watermelon $15.00
五、特性对比速查与选型决策
为了帮助读者在不同业务场景中快速挑选最契合的 API,并避免常见边界陷阱,下表全面汇总了现代字符串扩展方法的技术特性:
API 选型核心原则
- 布尔判断优先选用 includes / startsWith / endsWith:只有当确实需要获得子串所在索引位置时(例如配合
slice拆解),才应该使用indexOf;若仅作为if分支判断条件,使用includes能彻底杜绝0值隐式转换风险并提升语义清晰度。 - 多条件与复杂模式匹配选用正则表达式:如果匹配规则包含“忽略大小写”、“多种可选模式”或“位置断言”,正则表达式(如
/^https?:/i)是更适合的工具;而在处理固定纯文本子串时,原生字符串方法因无正则解析与回溯开销,执行速度明显更优。 - Emoji 与 Unicode 代理对处理:JavaScript 字符串内部以 UTF-16 代码单元存储。单个复杂 Emoji(如
👍或合成表情)在length统计中计为 2 或更多代码单元。因此在使用padStart或repeat截断 Emoji 时可能造成乱码,处理特殊字符文本时建议使用扩展运算符[...str]进行码点解构。
总结
ES6 及 ES2017 带来的字符串扩展方法,虽然在单个 API 设计上保持了足够的轻量和克制,但它们系统性地重塑了 JavaScript 文本处理的基础体验。通过将 includes、startsWith、endsWith 用于条件分流,将 repeat 用于占位与层级排版,将 padStart 与 padEnd 用于格式化补齐与脱敏显示,开发者能够写出语义更明确、逻辑更健壮且更易于团队维护的高质量现代 JavaScript 代码。
JavaScript Math.round()四舍五入取整基础用法
2026-11-12 18:48:07
JS封装兼容浏览器与Node的字符串转Hex函数
2026-11-12 16:33:15
JS中设置length=0清空数组与重新赋值的区别
2026-11-12 14:46:01
JavaScript怎么直接截断小数部分实现取整
2026-11-12 10:25:56
JS数组indexOf和findIndex用法对比:查找元素索引的最佳实践
2026-11-11 15:39:38








