slice()

本文对lodash的slice方法进行源码解析。slice用于截取数组元素,返回新数组,它并非对Array.slice()的封装。该方法接收原数组、开始位置和结束位置三个参数,实现思路是根据参数计算新数组长度,生成新数组并遍历赋值。

_.slice(array, [start = 0], [end = array.length])

每天更新一个lodash方法源码解析

slice用于对数组元素进行截取,返回值为截取元素组成的一个新数组。slice方法很容易让人联想到Array.slice(),它是不是对Array.slice()的一层封装?答案是no,lodash自己实现了一个slice方法来替代Array.slice()方法。

在这里插入图片描述
官方文档中这句话也证明了,上面的话意思就是:使用该方法(_.slice())来替代Array.slice()以确保返回密集数组。

example:
_.slice([1, 2, 3, 4, 5], 2, 4)
// [3, 4]
_.slice([1, 2, 3, 4, 5])
// [1, 2, 3, 4, 5]

slice(array, [start = 0], [end = array.length])接收3个参数,第一个参数array为原数组,也就是将要截取的元素;第二个参数为start,数组截取开始时的位置,默认为0;第三个参数为截取结束时的位置,默认为原数组的长度,截取时截取的元素是不包含结束位置的元素的。

源码解析:
function slice(array, start, end) {
  // 如果array为null,length为0,否则取array.length
  let length = array == null ? 0 : array.length
  // 如果length为0,则返回空数组
  if (!length) {
    return []
  }
  // 判断第二个参数start有没有传值,没有传值则取0,传值则取传入的值
  start = start == null ? 0 : start
  // 判断第三个参数end有没有传值,没有传值则取array的长度,传值则取传入的值
  end = end === undefined ? length : end

  // 处理start小于0的情况
  // 如果start小于0且-start的值大于array的长度,则start取0,否则start取数组长度加start的值
  if (start < 0) {
    start = -start > length ? 0 : (length + start)
  }
  // 当end值大于数组长度时,end取数组的长度
  end = end > length ? length : end
  // 处理end小于0的情况
  // 当end小于0时,end取数组长度加end的值
  if (end < 0) {
    end += length
  }
  // 如果start大于end,则length取0,否则取end-start值
  // 其中(end-start) >>> 0作用是保证(end-start)是一个有意义的正整数,详细可参考这篇文章:https://segmentfault.com/a/1190000014613703
  // 执行下面语句后,length值将变为返回数组的长度
  length = start > end ? 0 : ((end - start) >>> 0)
  // 确保start为一个有意义的正整数
  start >>>= 0

  // 定义一个index,后面将作为数组result的索引值
  let index = -1
  // 定义返回数组result,其长度为length
  const result = new Array(length)
  // 遍历数组result,并将原数组array中index+start对应的元素添加到result数组中index对应的位置
  while (++index < length) {
    result[index] = array[index + start]
  }
  // 返回结果result
  return result
}

实现思路:根据start和end参数计算出返回数组的长度,利用返回数组长度生成一个新数组,然后遍历该新数组,并将原数组中index+start对应的值给到新数组index对应的位置。

2019/6/17

07-08
在IT领域中,"slice" 一词通常与编程语言中的数据结构和操作相关。以下是对 "slice" 的详细解释: ### 数据结构中的 Slice 在编程语言中(如Go、Python等),**Slice 是一种灵活的数据结构**,用于表示对底层数组的抽象。它通常包含三个核心组成部分: 1. **指针(Pointer)**:指向底层数组的起始位置。 2. **长度(Length, len)**:表示当前 Slice 中元素的数量。 3. **容量(Capacity, cap)**:表示从指针开始到底层数组末尾的元素总数。 例如,在 Go 语言中,可以使用 `make` 函数创建 Slice: ```go slice := make([]int, 5, 10) ``` 上述代码创建了一个长度为 5、容量为 10 的整型 Slice。底层数组会分配足够的空间以容纳 10 个元素,但当前 Slice 只能访问前 5 个元素[^2]。 ### Slice 的常见操作 1. **初始化 Slice** - 使用字面量直接定义: ```go slice := []int{1, 2, 3} ``` - 使用 `make` 函数指定长度和容量: ```go slice := make([]int, 5, 10) ``` - 初始化时底层调用 `runtime.makeslice` 来分配内存[^1]。 2. **扩展 Slice** - 使用 `append` 操作向 Slice 添加元素。当 Slice 的长度超过容量时,底层数组会被重新分配更大的空间,并将旧数据复制过去。此过程涉及 `runtime.growslice` 的调用。 3. **切片操作** - 使用索引操作获取子 Slice,例如: ```go subSlice := slice[2:5] ``` 此操作不会复制底层数组,而是创建一个新的 Slice 结构体,指向原数组的一部分。 ### 其他上下文中的 Slice 1. **字符串操作中的 Slice** - 在 JavaScript 等语言中,`slice()` 方法用于提取字符串的部分内容。例如: ```javascript var str = "Hello,world!"; var sliceStr = str.slice(1, 5); // 输出 "ello" ``` `slice(start, end)` 方法支持负数索引,例如: ```javascript var sliceStr = str.slice(-3); // 输出 "rld!" ``` 这种方法常用于处理字符串片段[^3]。 2. **Slice 与其他方法的区别** - `slice(start, end)` 和 `substring(start, end)` 类似,但不支持负数索引。 - `substr(start, length)` 则是根据起始位置和长度提取字符串。 ### Slice 的性能特性 - **高效性**:Slice 不需要频繁分配新内存,因为它可以复用底层数组。 - **动态扩容**:当通过 `append` 扩展 Slice 超出容量时,系统会自动调整底层数组的大小,通常是按指数增长策略。 - **零拷贝设计**:Slice 的切片操作不会复制数据,仅改变指针、长度和容量,因此效率非常高。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值