JS 中七个改变原数组的方法解析

1,391 阅读5分钟

前言

在 js 数组方法中,有七个方法对数组进行操作会直接改变原数组,就是这七个:pushpopshiftunshiftsplicesortreverse。我们都知道 vue2.x 中是通过 Object.defineProperty 实现数据的响应式,但是 Object.definePropety 方法是不能直接操作原数组的,比如如果使用这七个方法去改变原数组,改变之后的数据并不会实现响应式,所以 vue2.x 是对数组这七个方法做了重写的,实际上你调用的这几个方法并不是原生的,而且 vue2.x 重写的方法。那就让我们来看看这几个方法的作用吧。

image.png

1.push

向数组的末尾添加一个或更多元素,并返回新的长度。改变原数组。这个方法应该是数组中常用的一个之一,这个方法类似栈中的入栈

let arr = [1,2,3];
// 向数组末尾添加一个 4,原数组arr 变成 [1,2,3,4],并且返回新数组的长度:n = 4
let n = arr.push(4);
// arr 还可以传入多个参数,会按照顺序依次 push 到数组末尾
// 向数组 [1,2,3,4] 添加 1,2,3,4,原数组arr变成[1,2,3,4,1,2,3,4],返回新数组长度:m = 8
let m = arr.push(...arr);
console.log(arr); // [1,2,3,4,1,2,3,4]
console.log(n); // 4
console.log(m); // 8

2.pop

删除并返回数组的最后一个元素。改变原数组。这个方法类似栈中的出栈

let arr = [1,2,3];
// 删除并返回该数组中的最后一个元素,原数组arr变成[1,2]; cur: 3
let cur = arr.pop();
console.log(arr); // [1,2]
console.log(cur); // 3
  • 使用 pushpop 实现类似栈的行为: 后进先出
// 栈是行为就类似咱们生活中的叠盘子,先放进去的最后拿出来
let arr = [];
arr.push(1); // [1]
arr.push(2); // [1,2]
arr.push(3); // [1,2,3]
arr.pop(); // 3
arr.pop(); // 2
arr.pop(); // 1

3.shift

删除并返回数组的第一个元素。改变原数组。

let arr = [1,2,3];
// 删除并返回该数组中的第一个元素,原数组变成 [2,3]; n: 1
let n = arr.shift();
console.log(arr); // [2,3]
console.log(n); // 1

4.unshift

向数组的开头添加一个或更多元素,并返回新的长度。改变原数组。

let arr = [1,2,3];
// 向原数组的开头添加一个4并返回新数组的长度, 原数组变为 [4,1,2,3]; n: 4
let n = arr.unshift(4);
// 向原数组的开头添加 4,1,2,3,并返回新数组的长度,原数组变为[4,1,2,3,4,1,2,3]; m: 8
let m = arr.unshift(...arr);
console.log(arr); // [4,1,2,3,4,1,2,3]
console.log(n); // 4
console.log(m); // 8

5.splice

用于删除、添加或者替换数组中的某些元素; 返回被删除或被替换元素组成的数组。改变原数组。 用法

// howmany 和 item 都是可选
// howmany 没传就是删除从 index 开始到原数组结尾的所有元素
// item 没传就是删除后不往删除的位置里添加元素
arr.splice(index, [howmany], [...item])
  • 1.删除数组中的某些元素
let arr = [1,2,3,4];
// 从原数组的下标为 2 开始,删除length - 2个元素,原数组变成 [1,3];返回 [3,4]
// 这里 arr.splice(2) 等价于 arr.splice(2, arr.length - 2)
let m = arr.splice(2);
console.log(arr); // [1,2]
console.log(m); // [3,4]
  • 2.删除数组中的某些元素并替换成新的元素
let arr = [1,2,3,4];
let arr1 = [1,2,3];
// 原数组从下标为 1开始,删除两个元素,并且在删除的位置添加 1,2,3,原数组变成 [1,1,2,3,4];返回 [2,3]
let newArr = arr.splice(1,2, ...arr1);
console.log(arr); // [1,1,2,3,4] 
console.log(newArr); // [2,3]
  • 3.更新数组中的某一个元素
let arr = [1,2,3,4];
// 原数组从下标2开始,删除一个元素,并且在 2 下标的为添加 8,来达到一个更新数组中的一个元素
let newArr = arr.splice(2, 1, 8);
console.log(arr); // [1,2,8,4]
console.log(newArr); // [3]
  • 4.当指定的开始下标(index)不存在时,会在原数组的末尾添加一个或多个新元素,此时它的作用和push一样。
let arr = [1,2,3,4];
// 下标 6 不存在,往数组末尾添加 9,删除的元素为空,所以返回空数组
let n = arr.splice(6,1,9);
console.log(arr); // [1,2,3,4,9]
console.log(n); // []

6.sort

对数组的元素进行排序并返回排序后的数组。改变原数组。

  • 基本使用
let arr = [1,5,3,7,6];
let n = arr.sort();
console.log(arr); // [1, 3, 5, 6, 7]
console.log(n); // [1, 3, 5, 6, 7]

再看下面一个例子

let arr = [6,8,1,30,5];
arr.sort();
console.log(arr); // [1, 30, 5, 6, 8]

看着上面排序的结果是不是感觉和奇怪,并不是自己想像的结果。其实数组的sort方法当没有参数传入的时候,其排序顺序默认为,将待排序数据转换为字符串,并按照Unicode序列排序;所以这里sort默认的排序并不是按照值来排序,想要实现值的排序就需要传入一个比较函数了。该函数比较两个值的大小,然后返回一个用于说明这两个值的相对顺序的数字。具体是排序原理是用的 v8 引擎里的插入排序和快速排序,v8引擎排序源码。当数组长度小于等于10的时候,采用插入排序,大于10的时候,采用快排。

比较函数有两个参数 a 和 b,其返回值如下:

若 a 小于 b,即 a - b 小于零,则返回一个小于零的值,数组将按照升序排列。

若 a 等于 b,则返回 0,数组顺序不变。

若 a 大于 b, 即 a - b 大于零,则返回一个大于零的值,数组将按照降序排列。

let arr = [1,5,3,7,6];
arr.sort((a,b) => 0);
console.log(arr); // [1, 5, 3, 7, 6]
arr.sort((a,b) => a - b);
console.log(arr); // [1, 3, 5, 6, 7]
arr.sort((a,b) => b - a);
console.log(arr); // [7, 6, 5, 3, 1]

7.reverse

反转数组中元素的顺序并返回新数组。改变原数组。

let arr = [3,8,7,6];
let newArr = arr.reverse();
console.log(arr); // [6, 7, 8, 3]
console.log(newArr); // [6, 7, 8, 3]