JS中从Array.slice()与Array.splice()的底层实现原理分析区别

javascript数组splice和slice介绍 slice 是 JavaScript 数组对象的一个方法,用于返回数组的一个片段(浅拷贝)。,包含从开始索引到结束索引(不包括结束索引)之间的元素。 阅读详情

1.Array.prototype.slice()
slice() 方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对像,原始数组不会改变。

arrayObject.slice(start,end)
  • start (可选,如果start不写则从0开始)从该索引处开始提取原数组中的元素。
    如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2)表示提取原数组的倒数第二个元素到最后一个元素(包含最后一个元素)。
  • end(可选)在该索引处结束提取原数组元素(从0开始)。slice会提取原数组中索引从 begin 到 end 的所有元素(包含begin,但不包含end)。
    *1.如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。 slice(-2,-1)表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。
    2.如果 end 被省略,则slice 会一直提取到原数组末尾。
    3.如果 end 大于数组长度,slice 也会一直提取到原数组末尾。*
    原理:
    (应该都能看懂)
// This will work for genuine arrays, array-like objects, 
    // NamedNodeMap (attributes, entities, notations),
    // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
    // and will not fail on other DOM objects (as do DOM elements in IE < 9)
    Array.prototype.slice = function(begin, end) {
      // IE < 9 gets unhappy with an undefined end argument
      end = (typeof end !== 'undefined') ? end : this.length;

      // For native Array objects, we use the native slice function
      if (Object.prototype.toString.call(this) === '[object Array]'){
        return _slice.call(this, begin, end); 
      }

      // For array like object we handle it ourselves.
      var i, cloned = [],
        size, len = this.length;

      // Handle negative value for "begin"
      var start = begin || 0;
      start = (start >= 0) ? start : Math.max(0, len + start);

      // Handle negative value for "end"
      var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
      if (end < 0) {
        upTo = len + end;
      }

      // Actual expected size of the slice
      size = upTo - start;

      if (size > 0) {
        cloned = new Array(size);
        if (this.charAt) {
          for (i = 0; i < size; i++) {
            cloned[i] = this.charAt(start + i);
          }
        } else {
          for (i = 0; i < size; i++) {
            cloned[i] = this[start + i];
          }
        }
      }

      return cloned;
    };

还可以查看V8源码第587行:直达

2.Array.prototype.splice()
splice()方法通过删除现有元素和/或添加新元素来更改一个数组的内容。
原型:Array.prototype.splice (start, deleteCount, item1, item2, … )

  • start
    指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从1计数)。
  • deleteCount (可选)
    整数,表示要移除的数组元素的个数。如果 deleteCount 是 0,则不移除元素。这种情况下,至少应添加一个新元素。如果 deleteCount 大于start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)。
  • item1, item2, …(可选)
    要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。
    源码:
function ArraySplice(start, delete_count) {
  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.splice");

  var num_arguments = arguments.length;
  var array = TO_OBJECT(this);
  var len = TO_LENGTH(array.length);
  var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
  var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
                                           start_i);
  var deleted_elements = ArraySpeciesCreate(array, del_count);
  deleted_elements.length = del_count;
  var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;

  if (del_count != num_elements_to_add && %object_is_sealed(array)) {
    throw %make_type_error(kArrayFunctionsOnSealed);
  } else if (del_count > 0 && %object_is_frozen(array)) {
    throw %make_type_error(kArrayFunctionsOnFrozen);
  }

  var changed_elements = del_count;
  if (num_elements_to_add != del_count) {
    // If the slice needs to do a actually move elements after the insertion
    // point, then include those in the estimate of changed elements.
    changed_elements += len - start_i - del_count;
  }
  if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) {
    %NormalizeElements(array);
    if (IS_ARRAY(deleted_elements)) %NormalizeElements(deleted_elements);
    SparseSlice(array, start_i, del_count, len, deleted_elements);
    SparseMove(array, start_i, del_count, len, num_elements_to_add);
  } else {
    SimpleSlice(array, start_i, del_count, len, deleted_elements);
    SimpleMove(array, start_i, del_count, len, num_elements_to_add);
  }

  // Insert the arguments into the resulting array in
  // place of the deleted elements.
  var i = start_i;
  var arguments_index = 2;
  var arguments_length = arguments.length;
  while (arguments_index < arguments_length) {
    array[i++] = arguments[arguments_index++];
  }
  array.length = len - del_count + num_elements_to_add;

  // Return the deleted elements.
  return deleted_elements;
}

还可以查看V8源码第660行:直达
或者开发文档:ECMA5.1文档


请注意
1.splice() 方法会直接对数组进行修改。slice() 不对数组进行修改,原数组不会改变。
2.splice() 返回值为被操作的值。slice() 以新的字符串返回被提取的部分。
3.
[14, 3, 77].slice(1, 2) // [3]
[14, 3, 77].splice(1, 2) // [3, 77]

4.splice先执行删除操作,删除指定个数的元素,然后再插入elements(元素或数组),他的每次删除都涉及大量元素的重新排列,而在插入元素时引入队列来管理。所以splice()的效率不高

JavaScript数组核心方法详解:push/pop/shift/unshift/slice/splice实战指南 数组是编程中处理有序数据集合的基础数据结构,其核心操作原理在于对元素索引位置的高效管理。在JavaScript中,数组方法如push、pop、shift、unshift、slice和splice,分别对应尾部增删、头部增删、截取复制和原位修改等不同操作模式,这些方法共同构成了数组数据处理的底层能力。理解这些方法的差异与适用场景,对于实现栈、队列等数据结构,以及优化数据操作性能具有重要技术价值。在实际开发中,数组操作广泛应用于任务队列管理、列表数据分页更新、状态管理等场景。本文聚焦于数组的增删改查核心方法,通 阅读详情

相关推荐

JavaScript filter() 方法原理、陷阱与工程实践指南

filter() 是 JavaScript 数组的高阶函数,本质是基于布尔判断的纯函数式遍历操作,其核心原理是创建新数组并仅保留回调返回真值(truthy)的元素。它不修改原数组、无副作用,因此被广泛用于 React/Vue 响应式计算、数据清洗和前端安全过滤等场景。但因对返回值类型敏感(必须为布尔逻辑),新手常因隐式转换、遗漏 return 或未处理 null/undefined 导致 'filter failed' 等运行时问题;同时在大数据量或复杂回调中易引发性能瓶颈。本文结合 filter 和 ма

转些好文章,促进分享。 421

Array的操作方法之splice()

前言 今天在leetcode上做了一道合并两个有序数组的题目,用了splice()这个方法,于是打算做小笔记加深印象。 一、splice()的作用及使用 具有删除、插入。替换三个作用,该方法返回的是一个数组(包含从原数组中删除的项(若没有删除项则返回一个空数组)) 语法: splice(index,howmany,item1,…itemx); index——必须,整数,规定添加或者删除的位置,使用负数,从数组尾部规定位置。 howmany——必须,要删除的数量,如果为0,则不删除项目。 item1,…i

weixin_46536890的博客 1万+

解决若依Vue3前后端分离---路由切换时显示白屏

解决基于Vue3若依前后端分离项目中出现的路由正常切换但是就是不显示数据的问题,也就是不发起网络请求的问题。

简单点的博客 1605

Js-基础语法学习-splice()方法

正在自学JavaScript,以下为基础学习记录,方便后续查看巩固

m0_46906988的博客 2145

中文实体关系抽取数据集大盘点:从百度Duie2.0到医疗CBLUE,哪个更适合你的NLP项目?

本文全面分析了中文实体关系抽取领域的主流数据集,包括百度DuIE 2.0、医疗CBLUE等,帮助开发者根据项目需求选择最适合的数据集。文章详细对比了各数据集的特点、适用场景及优化策略,为自然语言处理项目提供实用指南。

weixin_29284657的博客 121

变焦跟踪理论基础(如何在变焦过程中保持清晰)

如何在整个变焦过程中一直保持图像的清晰度或焦点是变焦跟踪的主要挑战。 当用户在缩放跟踪的情况下改变缩放时,设备保持对焦。 然而,在没有变焦跟踪的情况下,图像变得失焦,图像在变焦跟踪后由于自动对焦(AF)算法才最终对焦。...................................................

ChenYX的博客 20万+

JS Array 方法 | 区分 slice 和 splice

slice(起, 终),切片 ,复制返回新数组不改原数组splice起, 删几个, 插入哪几个)增删改改原数组,返回被改后的原数组。

weixin_42479421的博客 2452

PFC胶结模型实战:从线性到平行粘结的力学行为解析

本文深入解析了PFC中线性接触与平行粘结(pb模型)的核心差异与应用。平行粘结模型通过模拟胶结层的力学行为,能够有效传递拉力和抵抗弯矩,是模拟岩石、混凝土等胶结材料的关键。文章详细介绍了其变形与强度参数的设置、法向与切向行为的验证方法,并揭示了全量与增量力计算中易出现的“幽灵力”问题及其解决方案,为复杂模型的构建与调试提供了实用策略。

weixin_29230773的博客 1205

js 数组方法 - 子数组操作 - splice()

因为splice 是直接操作并修改数组的,所以当找到数字3时在循环中的 i 下标是2,而当删除数字3后,数组下标 i 位置中保存的数字变为了数字4,然后到了下一个循环 i 下标为3时,数组下标 i 位置中保存的数字是5,所以跳过了数字4,于是调试信息中没有数字4。(3)若label和value相同,不往arr3中添加arr1中的对象;若arr1对中对象的value,arr3中没有,这个对象直接添加到arr3中。定一个数组,假设我要把中间的数字3删掉,数字3是数组下标2的元素,而且只需删掉1个数字。

weixin_41173973的博客 2518

USB通讯速度翻倍秘诀:手把手教你用WinUsb替代HID协议(附Zadig驱动配置图解)

本文详细介绍了如何通过WinUsb技术替代传统HID协议,实现USB通讯速度的显著提升。从技术对比、实现原理到Zadig驱动配置图解,手把手教你完成免驱高速通讯方案,适用于数据采集、固件升级等场景,实测速度可达HID协议的2倍以上。

weixin_29168675的博客 133

毕设-YOLOv8-OBB 实现自有数据集缺陷旋转检测全过程记录

这次项目让我深入理解了 YOLOv8-OBB 的原理和使用流程。步骤内容工具数据标注制作倾斜缺陷样本格式转换从 HBB 转换为 OBB模型训练使用 Ultralytics YOLOv8 OBBCLI 命令模型测试推理与结果可视化通过 OBB 模型,我的缺陷检测系统获得了更高的精度和鲁棒性。未来我打算继续优化数据增强方式,比如引入随机旋转、仿射变换等,让模型更适应不同角度的样本。

FJN110的博客 446

JavaScript数组核心方法深度解析:从push到splice的实战应用与性能优化

数组是编程中用于存储有序集合的基础数据结构,其核心操作原理基于对内存中连续元素的索引管理。在JavaScript中,数组方法如push、pop、shift、unshift、slice和splice不仅是实现数据增删改查的工具,更是构建高效数据流和状态管理的技术基石。这些方法通过直接操作数组长度和元素索引,为前端开发提供了处理列表数据、实现队列/栈结构、进行数据拷贝与合并等能力,直接影响应用性能与代码健壮性。例如,push和pop方法在实现任务队列时能高效处理尾部操作,而splice方法则像瑞士军刀一样支持灵

weixin_34357928的博客 408

云计算 | 期末梳理(上)

2024云计算回忆版 && 复盘向梳理

知识库搭建ing 2231

slice(),splice(),split(),substring(),substr()使用方法和区别

slice(),splice(),split(),substring(),substr()使用方法和区别

Nicole_0314的博客 1943

[QMT量化交易小白入门]-十二、QMT回测龙头打首板和连板的策略

class a():passA = a() #创建空的类的实例 用来保存委托状态field_list定义了需要的市场数据字段,而类a用于保存交易状态。

木头大左的博客 4757

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

有关 Array.prototype.slice.call() 和 Array.prototype.slice.apply() 方法的详解

对 Array.prototype.slice.call() 和 Array.prototype.slice.apply() 的简要理解 1. 逐步拆分解析 slice:可从已有的数组中返回选定的元素,不改变原数组。 注:有关 splice 方法的详解可参考 有关 Array.prototype.slice() 方法的详解 Array:Array 是 javascript 的一个引用类型,Array.prototype 属性表示 Array 构造函数的原型,其上有一个方法叫 slice()。 注:因此,

weixin_45242865的博客 4386

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Array.slice 8种不同用法

JS数组slice方法是JS语言中最强大、最常用的内建函数之一。 随着React和其他面向功能的JavaScript实践的兴起,它变得越来越重要,原因有两个: 函数式编程,尤其是高阶函数,与数据列表密切配合 函数式编程需要纯函数,即不会产生副作用或修改输入数据的函数 JavaScript 数组slice方法符合这两个标准。 slice方法可以在不修改原始列表的情况下创建列表子集的浅拷贝。因...

新技术革命 1457

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

js 数据类型的区别 内置对象Array

/表示通过数组的构造函数 使用new调用 创建数组对象。includes('元素') //判断是否包含指定的元素 包含返回true 不包含返回false。pop()和shift()返回值都是被删除的元素(会改变原数组)可以一次传入多个数据 这个方法的返回值是增加后的数组的新长度。可以判断是否是数组,是数组返回true,不是数组返回false。如果是两位数的数字元素 组成的数组 则需要使用以下方法排序。返回值是将被截取到的元素放到一个新数组里面,不会改变原数组。return a-b;

m0_47045804的博客 712

JavaScript字符串截取:substring、substr与slice核心差异解析

字符串截取是前端开发中最基础的字符串操作之一,涉及索引定位、长度控制、负数处理及Unicode安全等关键概念。其底层原理关系到浏览器兼容性、运行时性能与线上稳定性。`substring`采用左闭右开区间模型并自动归一化参数,`substr`基于起始+长度语义但已被ECMAScript标准标记为deprecated,而`slice`凭借统一的负数支持、无隐式交换和优异的跨平台一致性,成为现代JavaScript工程实践中的首选方法。本文深入剖析三者在参数逻辑、引擎实现、UTF-16码元处理及真实故障场景中的表

weixin_34318326的博客 426

s基础进阶--关于Array.prototype.slice.call(arguments) 的思考

Array.prototype.slice.call(arguments)的作用为:强制转化arguments为数组格式,一般出现在框架活插件的源码中 如何理解 上面的代码等价于[ ].slice.call(arguments) 或者随便一个数组调用都行 [1,2,4].slice.call(arguments) 因为,前面的调用者的作用只是沿着原型链向上找,最终找到Array为止,slice为A...

weixin_41766191的博客 269

给array添加元素_JavaScript原生函数之Array

目录数组的本质Array构造方法Array实例方法 join()concat()reverse()slice()splice()sort()map()forEach()filter()some() 和 every()reduce() 和 reduceRight()数组的本质 在讲Js原生函数Array之前,我们先探讨一下数组的本质。先给出结论:数组是一个原型链上包含Array.prototype的...

weixin_39804335的博客 285

理解 Array.prototype.slice.apply

1. 首先,我们都理解在js中改变this引用有三种方法,call(), apply(), bind(); 2. bind方法是改变函数内this引用,简单不再描述; 3. 至于 call() 和 apply() 两个方法,区别在于,前者是不定长的入参,后者是一个数组;下边重点说apply方法使用; 原理:     我们知道js中存在一种类数组对象,比如 {0:1,length:1} 

shilu89757的专栏 4005

常见JS面试相关问题

1,let和const的区别 在js中,let和const是创建变量的不同方式。 在早期的js中,咱们使用var关键字来创建变量。 let和const关键字是在ES6版本中引入的,其目的是在js中创建两种不同类型的变量,一种是不可变的,另一种是可变的。 const:它用于创建一个不可变变量。不可变变量是指其值在程序的整个生命周期中永不改变的变量。 let: let用于创建一个可变变量,可变变量是像...

吃太多会胖哦的博客 242

JavaScript数组方法回顾与详解

JavaScript数组方法回顾与详解(汇总)

橘子味阳光的博客 848

JavaScript数组访问器方法原理与工程实践指南

JavaScript数组访问器方法是一组不修改原数组、返回新数据的只读操作函数,其底层基于不可变性原则与引擎级优化(如V8的预分配和SIMD向量化)。它们通过统一的语义协议(如SameValueZero比较、toString隐式调用、浅拷贝机制)实现安全的数据探查与转换,在函数式编程、状态管理、前端监控等场景中承担关键角色。掌握concat、join、slice、includes等核心方法的行为边界与性能特征,能有效规避null/undefined隐式转换、引用穿透、稀疏数组误判等高频工程陷阱,并为toRe

weixin_30617737的博客 396

js 加总数组中某一列_查缺补漏从详细操作js数组到浅析v8中array.js

前言最近在写面试编程题,经常用到数组,经常想偷个懒,用它提供的方法,奈何还是对数组方法使用不熟练,导致写了很多的垃圾代码,很多地方稍加修改的话肯定变得简洁高效优雅?所以✍这篇文章本着了解一下JavaScript数组的特性,正如标题所写「通过v8中array.js源码浅析如何自己实现常见的数组方法」,如果你想提高自己编码能力,可以留下来看看这篇文章「阅读完,你将收获?」对常见数组操作方法更...

weixin_28930033的博客 184
上一篇: js中Array.sort()实现原理
下一篇: js赋值 浅拷贝 深拷贝
coder_chenz
博客等级 码龄10年 8粉丝 12原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值