JS substring和substr能截取字符串最后两位吗
深入解析JavaScript中substring和substr能否截取字符串最后两位。详细分析substr的负数索引支持与废弃状态、substring负数归零陷阱与实现方式,并对比现代标准推荐的slice方法。
核心结论:substr 原生支持负数索引,可以直接使用 str.substr(-2) 截取最后两位,但该方法已被 ECMAScript 规范废弃;substring 不支持负数索引,直接传入 str.substring(-2) 会将负数强制当作 0 处理而返回完整字符串,必须配合字符串长度写成 str.substring(str.length - 2) 才能实现截取。现代 JavaScript 开发中,官方推荐的标准方法是直接使用 str.slice(-2)。
在前端业务开发或数据解析过程中,获取字符串末尾指定长度的内容是极其常见的需求。例如:提取身份证后两位进行脱敏展示、获取文件扩展名、或者格式化日期前导补零(如 ("0" + month).slice(-2))。开发者在面对 substring 和 substr 这两个名称高度相似的 API 时,往往会产生混淆:它们是否支持传入负数来倒数截取?本文将逐个分析两个方法的内部原理、执行机制与正确用法。
一、substr 能截取最后两位吗?
先给确切答案:能直接截取,但强烈不推荐在生产代码中继续使用。
String.prototype.substr() 的方法签名为 str.substr(start[, length])。它的第一个参数 start 表示截取的起始位置,第二个参数 length 表示截取的字符个数。
当传入的 start 为负数时,substr 内部会将负数解释为从字符串末尾开始倒数。计算逻辑如下:起始位置等于 str.length + start。如果未指定 length 参数,则默认截取到字符串末尾。
const text = "JavaScript";
// 1. 传入 -2,不传 length,默认截取到末尾
const result1 = text.substr(-2);
console.log(result1); // 输出: "pt"
// 2. 传入 -2 并显式指定截取长度为 2
const result2 = text.substr(-2, 2);
console.log(result2); // 输出: "pt"
在 ECMAScript 规范中,String.prototype.substr 已被列入附录 B(Annex B: Additional ECMAScript Features for Web Browsers),属于已被官方废弃(Deprecated)的遗留方法。虽然现代浏览器为了向下兼容依然实现了它,但部分严格模式工具、Node.js 规范检查插件(如 ESLint 的 no-restricted-properties 或 TypeScript 编译器)都会对 substr 触发废弃警告。
二、substring 能截取最后两位吗?
直接给确切答案:不能直接通过负数截取;但如果手动传入 length - 2,可以成功截取。
String.prototype.substring() 的签名是 str.substring(indexStart[, indexEnd])。很多初学者以为它像数组切片一样能识别负数,直接写出 str.substring(-2),结果却大失所望。
1. 直接传负数的“归零陷阱”
ECMAScript 规范对 substring 的参数规范化有如下强行转换规则:
- 负数与 NaN 归零:任何小于 0 或为
NaN的参数值,都会被强制替换为0。 - 超限截断:任何大于
str.length的参数值,都会被强制替换为str.length。 - 参数调换:如果
indexStart > indexEnd,substring会在内部自动调换这两个参数的位置。
因此,当你执行 str.substring(-2) 时,底层实际发生了以下转换:
const text = "JavaScript";
// 错误写法:试图用负数倒数截取
const result = text.substring(-2);
// 实际内部执行:text.substring(0)
// 输出整串:"JavaScript",并没有截取出最后两位!
console.log(result); // "JavaScript"
2. substring 截取最后两位的正确写法
如果业务规范或旧项目要求必须使用 substring,则必须借助 str.length 显式算出倒数第二个字符的正向索引:
const text = "JavaScript";
// 正确写法:配合 length 属性
const result = text.substring(text.length - 2);
console.log(result); // "pt"
当字符串本身长度小于 2 位(例如 "A")时,text.length - 2 的值为 -1,由于 substring 会把 -1 规约为 0,因此执行 text.substring(0) 恰好会安全地返回原字符串 "A",不会引发报错。
三、现代开发最佳解法:为什么统一推荐 slice?
在现代前端与 Node.js 开发中,如果需要截取字符串最后两位,无论是从代码简练度、可读性还是标准规范来看,String.prototype.slice() 都是唯一推荐的最佳方案。
slice(beginIndex[, endIndex]) 原生支持负数索引。当传入负数时,它会自动从字符串末尾倒数计算:beginIndex = str.length + beginIndex。同时,slice 属于 ECMAScript 核心标准方法,绝无废弃风险。
const text = "JavaScript";
// 现代推荐写法:一行代码直接表达“倒数取两位”
const lastTwo = text.slice(-2);
console.log(lastTwo); // "pt"
四、实战操作与防御性封装
在实际业务代码中,字符串截取不仅需要选择正确的方法,还需要考虑参数的类型安全与边界场景(如字符串为 null、undefined,或者长度不足两位)。
1. 安全截取函数的实现步骤
- 入参校验:先判断输入是否为合法的字符串类型,若为
null或undefined则统一返回空串或默认值,避免TypeError: Cannot read properties of undefined。 - 使用 slice 进行末尾提取:直接调用
str.slice(-n),当字符串长度小于n时,slice也会自动且安全地返回整个字符串,不会抛出越界异常。 - 结果输出:确保调用方拿到的是干净预期的子字符串。
/**
* 安全截取字符串最后 N 位
* @param {string} input - 原始字符串
* @param {number} count - 截取的末尾字符位数,默认为 2
* @returns {string} 截取后的字符串
*/
function getLastChars(input, count = 2) {
// 步骤一:防御性空值与类型检查
if (typeof input !== "string") {
return "";
}
// 步骤二:使用标准的 slice 提取后 count 位
return input.slice(-Math.abs(count));
}
// 测试验证用例:
console.log(getLastChars("2026-11-01")); // 示例输出: "01"
console.log(getLastChars("A")); // 示例输出: "A" (长度不足,返回自身)
console.log(getLastChars("")); // 示例输出: ""
console.log(getLastChars(null)); // 示例输出: "" (类型安全,无异常)
五、总结与注意事项
回到文章标题的核心问题:“JS substring和substr能截取字符串最后两位吗?”
substr:语法上能够通过str.substr(-2)截取最后两位。但该 API 已从标准规范中废弃,只存在于浏览器兼容附录中,不建议在任何新代码中使用。substring:直接传入负数str.substring(-2)不能截取最后两位(负数会被转为 0,返回整串)。必须配合长度写为str.substring(str.length - 2)才能达到目的。- 现代首选:直接使用
str.slice(-2),语法优雅、符合标准、运行稳定,是截取字符串末尾几位最规范的行业通用解法。
JS处理含Emoji或中文的字符串转数组乱码问题
2026-11-05 16:12:28
JS怎么使用展开运算符合并对象
2026-11-05 14:42:18
ES6+环境下判断JS对象为空的简洁写法
2026-11-05 12:12:23
怎么通过replacer函数自定义JS中JSON的格式化输出
2026-11-05 11:19:44
JS正则表达式基础:字面量与RegExp构造函数的区别及常用元字符
2026-11-05 11:16:58








