JavaScript-实现数组方法-splice

28 阅读5分钟

介绍splice方法

用来给数组进行删除 替换 插入元素的操作 arr.splice(index,num,value) index 表示开始操作的索引 如果是负数那就从后往前数 num 表示操作的数量 从索引开始后几位 value 如果传入 表示替换或者插入的数组

  • 删除功能
const arr = [0, 1, 2, 3, 4]
    arr.splice(1, 1)
    console.log('应该输出的结果', arr);  //[0, 2, 3, 4]
  • 替换功能 此时传入value为替换的元素
  const arr = [0, 1, 2, 3, 4]
    arr.splice(1, 1, 'A')
    console.log('应该输出的结果', arr);  //[0, 'A', 2, 3, 4]
  • 替换并且插入元素 此时传入两个要替换插入的元素
 const arr = [0, 1, 2, 3, 4]
    arr.splice(1, 1, 'B', 'C')
    console.log('应该输出的结果', arr);  //[0, 'B', 'C', 2, 3, 4]

  • index为负数的情况 从后往前执行删除功能
  const arr = [0, 1, 2, 3, 4]
    arr.splice(-1, 1)
    console.log('应该输出的结果', arr);  //[0, 1, 2, 3]

原型链

用原型链重写数组方法

  • 使用prototypemySplice方法挂在数组原型链上 这样Array通过构造函数创建的实例可以继承上面的方法 原型链 创建的数组对象是Array的实例 实际上就是通过Array的构造函数创建brr1实例本质是语法糖

函数传参

arguments

arguments是传递给函数的参数 的类数组对象 包含传递给函数的所有参数

类数组对象

  • 只有索引和长度属性 没有Array内置方法 例如 forEach() map() 可以通过索引被引用 可以被赋值 类数组对象
  • 可以转换为真正的数组 通过Array.from方法 还有[...展开运算符] ![[Pasted image 20251031090136.png]]
callee属性
  • 指向参数所属的当前执行的函数
Symbol(Symbol.iterator) 属性
  • 返回数组迭代器对象 包含参数中每个索引的值 数组迭代器对象 允许数组被可迭代对象的语法使用 ![[Pasted image 20251031090012.png]]

剩余参数

表示不确定数量的参数 在函数的最后一个参数前加上... 是真正的数组 可以使用数组方法 剩余参数

二者之间

arguments后面塞进数组 就是剩余参数数组 在这里插入图片描述

最终使用

因为要拿到传入的要用来替换和插入的value值 是不确定数量的 所以用剩余参数 操作的索引index 和操作元素数量num后面传入的都是value值

this

  • 谁调用指向谁 哪个数组调用就指向哪个数组
  • 在里面用this表示调用的数组 对调用的数组进行操作

替换 插入 处理

如果values.length>0 就执行 表示有需要替换插入的元素

注意 这里括号里不能写value 没有元素传进来的话是空数组 空数组也返回true

替换

替换

  • 先 从index索引开始 替换次数为num
  • values数组里前num个替换到原数组里

插入

如果有超出numvalue 就要插入到相应位置![[Pasted image 20251031112740.png]]

  • 插入位置后面的元素向后移 元素向后移动的位数=还需要插入的元素个数=values.length-num插入
  • 最后再把相应元素插入:从处理完替换的索引index+num开始插入 values中后面没替换完的部分values[num]插入 这里变量移动和插入的关键值为valuse.length-num 要插入的元素数量也就是每个元素向后移动的位数和插入元素的次数我们把这个值存到key里方便使用

代码

     //替换
     if (values.length > 0) {
       for (let i = 0; i < num; i++) {
         // console.log('循环中被赋值', i, values[i]);
         this[index + i] = values[i]
       }
       let key = values.length - num
       //还有value值就插入
       if (key > 0) {
         //移动几位要根据剩下的数据决定
         for (let j = this.length - 1; j > index; j--) {
           //移动后面的元素
           this[j + key] = this[j]
         }
         console.log('移动完之后', this);
         for (let k = 0; k < key; k++) {
           this[index + num + k] = values[num + k]
         }
       }
     }

删除处理

如果没有传入value值 就直接从index开始删除num个元素 删除的本质是要删除的元素后面的元素向前移动 最后要处理删除后数组的长度 后面的元素向前移动 后面的值给前面 所以向后遍历 这里后面会详细解释 元素向前移动和向后移动的的遍历问题

代码

//删除              
      else {
        for (let i = index; i < this.length - num; i++) {
          this[i] = this[i + num]
        }
        //处理数组长度
        this.length -= num
      }
    }

索引为负数

只需要把负数索引 转换为相应的正数索引来处理就行 就是这个数组的长度加上这个负数 就能得到这个负数索引表示的数组索引

//负索引转换为正索引
      if (index < 0) {
        index = this.length + index
      }

最终代码

  const arr1 = [0, 1, 2, 3, 4]
    //实现splice 删除替换插入 负索引
    Array.prototype.mySplice = function (index, num, ...values) {
      //this 哪个数组调用 改变哪个数组
      console.log(values);

      //负索引转换为正索引
      if (index < 0) {
        index = this.length + index
        console.log(index);

      }
      //替换
      if (values.length > 0) {
        for (let i = 0; i < num; i++) {
          // console.log('循环中被赋值', i, values[i]);
          this[index + i] = values[i]
        }
        let key = values.length - num
        //还有value值就插入
        if (key > 0) {
          //移动几位要根据剩下的数据决定
          for (let j = this.length - 1; j > index; j--) {
            //移动后面的元素
            this[j + key] = this[j]
          }
          console.log('移动完之后', this);
          for (let k = 0; k < key; k++) {
            this[index + num + k] = values[num + k]
          }
        }
      }
      //删除              
      else {
        for (let i = index; i < this.length - num; i++) {
          console.log(this[i], this[i + num]);
          this[i] = this[i + num]
        }
        //处理数组长度
        this.length -= num

      }
    }

补充说明:移动方向和遍历方向

元素向前移动

从前往后遍历 本质上可以删除元素
往前移的意思是 元素的索引变小 后面的值给前面所以向后遍历去后面找值 元素向前移动 代码示例 ![[Pasted image 20251031113048.png]] 从后往前遍历是错误的 始终传递的是最后面的值 错误

元素向后移动

从后往前遍历 本质上可以插入元素 往后移的意思是 元素的索引变大 前面的值给后面 所以向前遍历去前面找值 元素向后移动 代码示例 代码 从前往后遍历是错误的 在这里插入图片描述