一文彻底搞懂slice方法的原理

428 阅读1分钟

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

目录

今日题

  1. 题目
  2. 分析 昨日题
  3. 题目
  4. 答案
  5. 解析 结语

今日题

题目

实现数组的join方法

分析

join方法用于将一个数组合并为字符串,并接收一个可选的参数,如果传入了该参数则合并时会以该参数为连接符将数组中的元素合并为新串,如果省略了该参数,则默认以逗号','来进行连接

昨日题

题目

实现Array##slice

答案

Array.prototype._slice = function (begin = 0, end = this.length) {
    var types = [begin, end].find(v => typeof v !== 'number')
    if (!!types) throw new TypeError(`${types} is not Number`)
    var lenArr = this.length, result = []
    var getPositiveNum = minus => lenArr + minus
    if (begin >= lenArr) return result
    else if (begin < 0) begin = Math.abs(begin) >= lenArr ? 0 : getPositiveNum(begin)
    if (end < 0) {
        if (Math.abs(end) >= lenArr) return result
        end = getPositiveNum(end)
    } else if (end >= lenArr) end = lenArr
    var i = 0, count = end - begin
    while (i++ < count) result.push(this[begin++])
    return result
}

解析

slice方法常用于截取数组中的元素,其规则为从开始位置的索引截取至结束位置的索引,且不影响原数组。该方法接收两个可选的参数beginend,其中begin截取的开始位置索引end截取的结束位置索引,且beginend均有正、负两种情况,再加上两个参数均可以自由省略,考虑到情况众多,所以我在这里根据原生数组slice方法的特性整理了一张脑图

slice.png

上图中包含了slice方法的所有情况,现在我们根据每个情况所具备的不同特点来实现它->

首先slice方法的两个参数beginend均为可省略参数,如果确认省略了该参数,则bengin的默认值为0end的默认值为数组长度,所以我们对_slice方法的两个形参赋以默认值

Array.prototype._slice = function (begin = 0, end = this.length) { //... }

倘若传入了参数,则最好要确保传入的参数为Number类型,所以在_slice方法中进行类型判断

var types = [begin, end].find(v => typeof v !== 'number')
if (!!types) throw new TypeError(`${types} is not Number`)

然后便是对beginend分别进行边界处理

// begin
if (begin >= lenArr) return result
else if (begin < 0) begin = Math.abs(begin) >= lenArr ? 0 : getPositiveNum(begin)
// end
if (end < 0) {
    if (Math.abs(end) >= lenArr) return result
    end = getPositiveNum(end)
} else if (end >= lenArr) end = lenArr

其中getPositiveNum方法的作用是通过负索引得到正索引,即正索引 = 数组长度 + 负索引

var getPositiveNum = minus => lenArr + minus

工欲善其事 必先利其器,至此所有情况均完成判断,我们只需对数组进行截取即可

var i = 0, count = end - begin
while (i++ < count) result.push(this[begin++])

用于测试的数组

var nums = ['唐', '宋', '元', '明', '清']
console.log(nums._slice()) // ['唐', '宋', '元', '明', '清']

结语

此文章已收录至《JavaScript每日一题》专栏,如果你对本专栏有任何建议,欢迎反馈。如果你对此文章中的题目还有不懂的地方,那么请在评论区留言与大家一起讨论吧。
创作不易,少年,就请留个赞再走吧!