JavaScript - 我独自升级 substr

只要有 substring 和 slice,就没什么好怕的。
 

在加入了陈年专案维护中获得了新知识。



 

前言

最近工作派发了一些 Legacy Code 专案翻修,难免会遇到一些 deprecated 的方法。

面对这些陈年代码,最大的敌人往往都是疏忽了商业逻辑以及代码可读性。

 

本篇重点不在于介绍 substr, substring, slice ,想必大家都略懂这方法。

如果使用冷门特性,你一辈子都会记得写注解对吧!?

 

这一篇的角度在于笔者对 Legacy Code 进行 String.substr() 重构的思路。

从「维护性」与「效能」的之间找到合适的平衡。

这份笔记也是为了日后仍遇到时,可以快速拿自己的文章参考。

希望能对大家有所帮助。



 

一、字串切割介绍

简单说明一下他们「主要」的用法。

最大的区别在于第二个参数「索引 Index」的意义。

String.prototype.substr() - MDN Web Docs

substr(start)
substr(start, length)

String.prototype.substring() - MDN Web Docs

substring(indexStart)
substring(indexStart, indexEnd)

String.prototype.slice() - MDN Web Docs

slice(indexStart)
slice(indexStart, indexEnd)

 

这些方法中,最大的差异在于:

  • 参数使用几个?
  • 传入的参数值是否为 ≥ 0?
  • 传入的参数值是否为 负数?



 

二、评估抽换方式

这篇是解决 Legacy Code 的场景,因此可以思考你面对的 substr() ,是为了解决什么问题?

接着来探索这些可能的条件,找出最适的解决方案!

极端的例子我相信是鲜少的,不太需要执着于极端案例。
难以长期传承商业逻辑的代码,最需要的是直观的可读性。

 

以下提供 7 种的例子,作为重构的选择:

  1. 基本使用 substr(start, length))
  2. 起始索引为负数 substr(-start, length) → 使用 slice()
  3. 长度超过字串长度 substr(start, length) → 使用 substring()
  4. 起始索引超过字串长度 substr(start, length) → 使用 slice()
  5. 单参数 substr(start) → 使用 substring()
  6. 起始索引为负数且超过字串长度 substr(-start, length) → 使用 slice()
  7. 无法使用 substring(start, end) 替代 substr() 的情境 → 使用 slice()

 

1 . 基本使用 substr(start, length)

适用于简单的範围撷取,用于单纯的商业逻辑。

const str = "JavaScript";
console.log(str.substring(4, 10)); // "Script"

使用 substring() 替换。

console.log(str.substring(4, 10)); // "Script"

substring(start, start + length) 直观表达了「从 start 位置撷取 length 个字元」,可读性极高。


 

2. 起始索引为负数 substr(-start, length) → 使用 slice()

substring() 不支援负数索引,因此需要 slice() 来替代。

const str = "Hello World";
console.log(str.slice(-5)); // "World"

使用 slice() 替换。

console.log(str.slice(-5)); // "World"

slice(-start) 直接从倒数第 start 个字元开始撷取,行为与 substr() 相同。
 

 

3. 长度超过字串长度 substr(start, length) → 使用 substring()

在一些未知长度的条件下,如果允许 length 超出範围,substr() 会自动调整,substring() 也有类似行为。

const str = "abcdef";
console.log(str.substring(2)); // "cdef"

使用 substring() 替换相对直观,slice() 你喜欢也可以使用。

console.log(str.substring(2, str.length)); // "cdef"

substring(start, end) 自动处理 end 超过範围的情况。

 

4. 起始索引超过字串长度 substr(start, length) → 使用 slice()

如果场景具有未知的起始索引,substring() 会自动交换 start 和 end,而有不同结果,这种条件建议使用 slice()

const str = "Hello";
console.log(str.slice(10, 13)); // "" (空字串)

使用 slice() 替换。

console.log(str.slice(10, 13)); // "" (空字串)

slice(start, end) 行为与 substr() 一致,会返回空字串。

 

5. 单参数 substr(start) → 使用 substring()

当 length 省略时,substr(start) 会提取到字串结尾,这与 substring(start) 行为相同。这应该是最简单的场境,单纯且单一参数。

const str = "Hello JavaScript";
console.log(str.substring(6)); // "JavaScript"

使用 substring() 替换。

console.log(str.substring(6)); // "JavaScript"

substring(start) 直觉地表示「从 start 开始到字串结尾」,可读性高。

 

6. 起始索引为负数且超过字串长度 substr(-start, length) → 使用 slice()

通常在于更多的演算方法。substring() 不支援负数索引,应该使用 slice()

const str = "Hello";
console.log(str.slice(-10, -7)); // "Hel"

使用 slice() 替换。

console.log(str.slice(-10, -7)); // "Hel"

slice(start, end) 在负索引时表现一致,适用于此场景。

 

7. 无法使用 substring(start, end) 替代 substr() 的情境 → 使用 slice()

substring() 无法处理负数索引,也无法撷取固定长度,因此 slice() 是更好的选择。

const str = "Hello World";
console.log(str.slice(-5, -2)); // "Wor"

错误的 substring() 替换。

console.log(str.substring(0, 3)); // "" (错误,因为 `substring()` 会将负数视为 0)

正确的做法应该用 slice()

console.log(str.slice(-5, -2)); // "Wor"

slice() 是唯一能够完全取代 substr() 在负索引情境下的选择。



 

三、结论

整体而言,应该根据重构的目的,以及代码的职责来决定适合哪一种。

  • 基于可读性优先:如果今天你在业务逻辑单纯,且索引範围固定时,substring() 可读性更高。
  • 基于效率且容错率高的场景:如果面对特定的演算或者複杂的计算,甚至索引可能是负数等等不稳定的条件,这时候使用 slice() 相对安全。

 

适合 substring() 的场景:

  • start 与 end 你能肯定商业逻辑为正数。
  • 需要撷取 固定範围,不考虑负索引。
  • 可读性佳,适用于基本的字串撷取。

适合 slice() 的场景:

  • 需要支援负数索引 substr(-start, length)
  • 起始索引超出字串长度时,应返回空字串。
  • 避免 start > end 情境时自动交换。

 

 

有勘误之处,不吝指教。ob'_'ov

 

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章

5 点赞(415) 阅读(67)