重写字符串截取

1,028 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

引子

这是我开启Js方法重写的第三篇,感兴趣的同学可以关注我的专栏一起学习共进步

今天来写一些JavaScript中字符串常用的两个截取方法,以及他们的区别

slice

slice()  方法提取某个字符串的一部分,并返回一个新的字符串,且不改变原字符串

参数:

  • @param {*} start 开始截取位置
  • @param {*} end 结束截取位置 <可选>

返回: 返回一个新的字符串

常规使用:
 let str = "hello world"
 console.log(str.slice(1, -2)); // ello wor
 console.log(str); // hello world

实现:

对比数组方法中的 slice,字符串中的会不那么复杂,只有几个要点:

start :如果省略该参数,则返回整个字符串;如果值为负数,会被当做数组长度加当前值,如:10 + - 3 = 7;

end:如果省略该参数,slice() 会一直提取到字符串末尾;与start一样如果为负值则会被当做数组长度加当前值

 String.prototype.myslice = function (start, end) {
     // 1. 由于不改变原字符串 则创建一个值保存修改后都字符串
     let str = ""
     // 2. 判断是否为负值 
     if (start < 0) start = this.length + start
     if (end < 0) end = this.length + end
     // 3. 判断是否超出范围或没传参数
     if (end === undefined || end > this.length) end = this.length
     if (start === undefined) start = 0
     // 4. 循环执行
     for (let i = start; i < end; i++) {
         str += this[i]
     }
     // 5. 返回新的字符串
     return str
 }

substring

slice() 方法返回一个字符串在开始索引到结束索引之间的一个子集,或从开始索引直到字符串的末尾的一个子集

参数:

  • @param {*} start 开始截取位置
  • @param {*} end 结束截取位置 <可选>

返回: 返回一个新的字符串

常规使用:
 let str = "hello world"
 console.log(str.substring(2,-2)); // he
 console.log(str); // hello world

实现:

这个方法相对来说比较特别,我一次用的时候还挺懵的,传入的参数执行与返回的结果与预期的不太一样,后面看了下文档才发现这方法规矩是真的多,但用起来也很灵活巧妙,能应对大部分场景

来看一下MDN给出的描述:

substring 提取从 startend(不包括)之间的字符。特别地:

  • end 以该数字为索引的字符不包含在截取的字符串内
  • 如果 start 等于 endsubstring 返回一个空字符串
  • 如果省略 endsubstring 提取字符一直到字符串末尾
  • 如果任一参数小于 0 或为 NaN,则被当作 0
  • 如果任一参数大于 stringName.length,则被当作 stringName.length
  • 如果 start 大于 end,则 substring 的执行效果就像两个参数调换了一样

这种规矩多的,就间接表示判断多( ̄︶ ̄) ,因此只要把所有基准都实现到位就可以了

 String.prototype.mysubstring = function (start, end) {
     // 1. 由于不改变原字符串 则创建一个值保存修改后都字符串
     let str = ""
     // 2. 判断没传参数
     if (!start) return undefined
     // 3. 如果头尾相等, 则返回空字符串
     if (start === end) return ""
     // 4. 判断是否超出范围
     if (start > this.length) start = this.length
     // 5. 判断是否超出范围
     if (end === undefined || end > this.length) end = this.length
     // 6. 若为负值或NaN则设置为0
     if (start < 0 || start == NaN) start = 0
     if (end < 0 || end == NaN) end = 0
     // 7. 如果起始位置大于结束位置, 则交换位置
     if (start > end) [start, end] = [end, start]
     // 8. 循环执行
     for (let i = start; i < end; i++) {
         str += this[i]
     }
     // 9. 返回新的字符串
     return str;
 }

这个方法实现起来也很简单,按照规范一步步去实现就好了

slice, substring, substr 的区别

ps:本来想着也手写 subtr的,结果人家快退休了(废弃),而且它的方法使用 substring 也可以实现

当时不熟悉的时候用着会想,既然截取都能实现,那他们三个的区别是什么?

举个栗子,现在有一串字符串 hello world ,分别使用同样的参数 -3 执行,他们三个方法所返回的结果是不同的;slicesubstr 会返回从后截取的 rldsubstring返回的是整个字符串;再来将参数改为 (2,-5)slice返回的是 llo wsubstring返回的是 he,而 substr 返回的是空字符串;

因此对应不同的场景还是要采用不同的方法实现,需要普通截取时使用 slice ,需要截取负值换位的则使用 substring,对于 stbstr 就可以不用去使用了 ( •̀ ω •́ )y

最后由于本专栏的所有重写文章都是独自实现的,如果对于本文有疑惑,还请指导勘正 (●'◡'●)