likes
comments
collection
share

JavaScript 数组的一些方法&&数组拷贝

作者站长头像
站长
· 阅读数 32

一、添加/删除

1、Array.unshift(newEle , newEle2 , newEle3 , ...)(改变原数组)

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

队列方法 栈数据结构的访问规则是LIFO(Last-In-First-Out,后进先出),而队列数据结构的访问规则是FIFO(First-In-First-Out,先进先出)

let a = [1,2,3,4,5];   
let b = a.unshift(-2,-1); 
//a:[-2,-1,1,2,3,4,5] 
//b:7  

2、Array.push(newEle , newEle2 , newEle3 , ...)(改变原数组)

向数组的 结尾 添加一个或更多元素,并返回新的长度

栈方法 栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构

let a = [1,2,3,4,5];   
let b = a.push(6 , 7); 
//a:[-2,-1,1,2,3,4,5,6,7] 

3、Array.shift()(改变原数组)

删除原数组 第一项,并返回删除元素的值;如果数组为空则返回undefined

队列方法 栈数据结构的访问规则是LIFO(Last-In-First-Out,后进先出),而队列数据结构的访问规则是FIFO(First-In-First-Out,先进先出)

let a = [1,2,3,4,5];   
let b = a.shift(); 
//a:[2,3,4,5] 
//b:1

4、Array.pop()(改变原数组)

删除原数组 最后一项,并返回删除元素的值;如果数组为空则返回undefined

栈方法 栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构

let a = [1,2,3,4,5];   
let b = a.pop(); 
//a:[1,2,3,4] 
//b:5

5、Array.concat(arr , arr2 , arr3 , ...)(不改变原数组)

连接值或其他数组

let a = [1,2,3,4,5];   
let b = a.concat(6,7); 
//a:[1,2,3,4,5] 
//b:[1,2,3,4,5,6,7] 

6、Array.slice(start,end)(不改变原数组)

从已有的数组中返回选定的元素 start包含 , end不包含

它和字符串的str.slice(start, end)方法类似, 就是将字符串替换为数组

let a = [1,2,3,4,5];   
let b = a.slice(2,5); 
//a:[1,2,3,4,5] 
//b:[3,4,5] 

我们也可以不带参数地调用它:arr.slice()会创建一个arr的副本。其通常用于获取副本,以进行不影响原始数组的进一步转换。

7、Array.splice(index,num,newEle ,newEle 2,newEle 3,...)(改变原数组)

(我是宠儿我自豪)

向/从数组中添加/删除项目,然后返回被删除的项目

index 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。

num 必需。要删除的项目数量。如果设置为 0,则不会删除项目。

newEle , newEle2 , ... 可选。向数组添加的新项目。

返回包含被删除项目的新数组,如果有的话。

let a = [1,2,3,4,5];
let b = a.splice(1,1);
//a: [1,3,4,5]
//b: [2]
a.splice(1,0,55);
//a:[1,55,2,3,4,5]
//b:[]

------------------------------假装分割线------------------------------

二、遍历

1、Array.forEach(改变原数组)

它允许为数组的每个元素都运行一个函数,该函数的结果(如果它有返回)会被抛弃和忽略。

------------------------------假装分割线------------------------------

三、转换

1、Array.map(改变原数组)

对数组的每个元素都调用函数,并返回结果数组

let arr = ["zhangsan", "lisi", "wangwu"].map(item => item.length);
console.log(arr); // 8,4,6

2、Array.sort(fn)(改变原数组)

对数组的元素进行排序,fn为排序方法函数

function sortFn(a,b){
  return a - b
}
let a = [1,3,5,4,2];
a.sort(sortFn)
//a: [1,2,3,4,5]

3、Array.reverse()(改变原数组)

数组倒序排列

let a = [1,2,3,4,5];   
let b = a.reverse(); 
//a:[5,4,3,2,1] 
//b:[5,4,3,2,1]  

4、Array.join(str)(不改变原数组)

方法用于把数组中的所有元素放入一个字符串。元素是通过指定的分隔符进行分隔的

如果不填参数,则使用逗号作为分隔符

let a = [1,2,3,4,5];
a.join('-')
//a: [1,2,3,4,5]
//b: 1-2-3-4-5

5、reduce/reduceRight(fn, initial)

第一个参数fn为一个累加函数, 第二个initial为初始值 如果不填写默认将arr的第一个为初始值

let arr = [1, 2, 3, 4, 5];

let result = arr.reduce((sum, current) => sum + current, 0);

console.log(result); // 15
 

------------------------------假装分割线------------------------------

四、搜索

1、Array.indexOf(item, from)/lastIndexOf(item, from)(不改变原数组)

返回某个指定的字符串值在字符串中首次出现的位置,对大小写敏感,没有出现指定字符串则返回-1

let a = [1,2,3,4,5];
let b = a.indexOf(2);
//a: [1,2,3,4,5]
//b: 1

2、Array.includes

Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。

该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。

[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true

没有该方法之前,我们通常使用数组的indexOf方法。indexOf方法有两个缺点:

一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。

二是,它内部使用严格相等运算符(===)进行判断,这会导致对NaN的误判

3、Array.find() / findIndex()

数组实例的find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。

数组实例的findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

[1, 4, -5, 10].find((n) => n < 0)
// -5

4、Array.filter

find 方法搜索的是使函数返回 true 的第一个(单个)元素。

如果需要匹配的有很多,我们可以使用 arr.filter

语法与 find 大致相同,但是 filter 返回的是所有匹配元素组成的数组:

let users = [
  {id: 1, name: "John"},
  {id: 2, name: "Pete"},
  {id: 3, name: "Mary"}
];

// 返回前两个用户的数组
let someUsers = users.filter(item => item.id < 3);

alert(someUsers.length); // 2

------------------------------假装分割线------------------------------

五、其它

ES6 数组的拓展

1、Array.from()

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};

// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']

// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

如果参数是一个真正的数组,Array.from会返回一个一模一样的新数组

2、Array.of

Array.of方法用于将一组值,转换为数组

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

Array.of总是返回参数值组成的数组。如果没有参数,就返回一个空数组。

3、数组实例的 copyWithin()

数组实例的copyWithin()方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。

它接受三个参数。

  • target(必需):从该位置开始替换数据。如果为负值,表示倒数。
  • start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示从末尾开始计算。
  • end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示从末尾开始计算。
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]

上面代码表示将从 3 号位直到数组结束的成员(4 和 5),复制到从 0 号位开始的位置,结果覆盖了原来的 1 和 2。

4、数组实例的fill()

fill方法使用给定值,填充一个数组。

fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置

['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']

5、数组实例的entries(),keys()和values()

ES6 提供三个新的方法——entries(),keys()和values()——用于遍历数组。它们可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。

如果不使用for...of循环,可以手动调用遍历器对象的next方法,进行遍历

5、数组实例的flat()、flatMap()

数组的成员有时还是数组,Array.prototype.flat()用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。

[1, 2, [3, 4]].flat()
// [1, 2, 3, 4]

flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。

[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]]

[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]

如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。

[1, [2, [3]]].flat(Infinity)
// [1, 2, 3]

------------------------------假装分割线------------------------------

六、数组拷贝

1、拓展运算符 【...】

扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

注意,只有函数调用时,扩展运算符才可以放在圆括号中,否则会报错

const a1 = [1, 2];
const a2 = a1;

a2[0] = 2;
a1 // [2, 2]

上面代码中,a2并不是a1的克隆,而是指向同一份数据的另一个指针。修改a2,会直接导致a1的变化。

const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;

上面的两种写法,a2都是a1的克隆

2、concat()

连接值或其他数组

如果我们不指定参数或者提供一个空数组作为参数,浅拷贝方法

const arr1 = [1, 2, 3, 4]
const arr2 = arr1.concat()
console.log('before push arr2', arr2)  //  [1, 2, 3, 4]

arr2.push(5)
console.log('after push arr1 :', arr1)  // [1, 2, 3, 4]
console.log('after push arr2 :', arr2)  // [1, 2, 3, 4, 5]

3、slice()

slice方法根据我们指定的start、end的index从原数组中返回一个浅拷贝的数组

当不给定参数时,就返回了原数组的拷贝

const arr1 = [1, 2, 3, 4]
const arr2 = arr1.slice(0,2)
console.log('before push arr2', arr2)  //  [1, 2, 3, 4]

arr2.push(5)
console.log('after push arr1 :', arr1)  // [1, 2, 3, 4]
console.log('after push arr2 :', arr2)  // [1, 2, 5]

4、Array.from

Array.form 方法从一个类似数组或可迭代对象中创建一个新的,浅拷贝的数组实例

console.log(Array.from('foo'));
// expected output: Array ["f", "o", "o"]

console.log(Array.from([1, 2, 3], x => x + x));
// expected output: Array [2, 4, 6]

手动分割线

let str = 'abc'
let strArr = Array.from(str)
console.log(strArr)   // ['a', 'b', 'c']
let arr = [1, 2, 3, 4]
let brr = Array.from(arr)
console.log(brr)      // [1, 2, 3, 4]
arr.push(5)
brr.push(10)
console.log(arr)      // [1, 2, 3, 4, 5]
console.log(brr)      // [1, 2, 3, 4, 10]

5、JSON.parse & JSON.stringify(深拷贝)

let arr = [[1], [2]]
let brr = JSON.parse(JSON.stringify(arr))
console.log(brr)    // [[1], [2]]
brr[0].push(6)
console.log(arr)    // [[1], [2]]
console.log(brr)    // [[1, 6], [2]]

此方法适用于Oject的深度拷贝,因为Array属于Oject类型,所以也适用于此处

注意事项参考 :

①、如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象

②、如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象

③、如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失

④、 如果obj里有NaN、Infinity或-Infinity,则序列化的结果会变成null

⑤、JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor

6、对象数组的深拷贝

      let obj = {
        name: 'zhangsan',
        age: 28,
        children: [
          { name: 'zhangsi', age: 2 }
        ]
      }
      
      function deepClone(tdata, odata) {
        for (let k in tdata) {
          // 判断数据类型
          let item = tdata[k]
          if (item instanceof Array) {
            odata[k] = []
            deepClone(item, odata[k])
          } else if (item instanceof Object) {
            odata[k] = {}
            deepClone(item, odata[k])
          } else {
            odata[k] = item
          }
        }
        return odata
      }

      let tx = deepClone(obj, {})
      console.log('deep test:', tx)
转载自:https://juejin.cn/post/7383957603016245263
评论
请登录