数组的扩展和新增方法

简介: 数组的扩展和新增方法

剩余运算符

剩余运算符:...变量

可以将数组的值解构成单个单个的参数序列

console.log(...[1,2,3,4,5]);  // 1 2 3 4 5
let { a, b, ...z } = { a: 1, b: 2, c: 3, d: 4 }
// a 1
// b 2
// z { c:3, d:4 }

剩余运算符是否为深拷贝的问题

1、剩余运算符如果只有一层,是深拷贝

// 数组
let a = [1,2,3,4]
let b = [...a]
b[0] = 5
console.log(a);  // [1,2,3,4]
console.log(b);  // [5,2,3,4]
// 对象
let aa = {name:'西方'}
let bb = {...aa}
bb.name = '求败'
console.log(aa);  // {name:'西方'}
console.log(bb);  // {name:'求败'}

2、剩余运算符如果有多层,数据是基本类型的,为深拷贝

let c = [1,2,3]
let d = [4,5,6]
let e = [...c,...d]
e[0] = 9
console.log(c); // [1, 2, 3]
console.log(d); // [4, 5, 6]
console.log(e); // [9, 2, 3, 4, 5, 6]

3、剩余运算符如果有多层,对象、数组内的参数序列是引用类型的,为浅拷贝。

内部的引用类型对象其实复制了指针,所以为浅拷贝,基础类型为深拷贝。

let a2 = [{name:'东方'},5]
let b2 = [...a2]
b2[0].name = '不败'
b2[1] = 6
console.log(a2);  // [{不败},5]
console.log(b2);  // [{不败},6]

Array.from()

Array.from()可以将类似数组对象或者可遍历对象转为真正的数组。

需要注意的是:必须得有length属性才可以转换。

// 错误的
   let ar = { 
        '0' : 'a',
        '1' : 'b',
        '2' : 'c',
console.log(ar);  // {0: 'a', 1: 'b', 2: 'c'}
console.log(ar.length); // undefined
console.log(Array.from(ar));  // []
// 正确的
   let ar2 = { 
       '0' : 'a',
       '1' : 'b',
       '2' : 'c',
        length : 3
     }
console.log(ar2);  // {0: 'a', 1: 'b', 2: 'c', length: 3}
console.log(ar2.length);  // 3
console.log(Array.from(ar2));  // ['a', 'b', 'c']

任何具有length属性的都可以通过Array.from()转为数组

Array.from({length : 3});  // [undefined, undefined, undefined]

Array.from()第二个参数可以将转换后的数组的每个元素处理并返回

Array.from([1,2,3],(x)=> x + 1);  // [2,3,4]
Array.from('123',(x)=> x + 1);  // ['11', '21', '31']

Array.from()返回的是一个新数组

let arr3 = [1,2,3]
let arr4 = Array.from(arr3,x => x +1)
console.log(arr3);  // [1,2,3]
console.log(arr4);  // [2,3,4]

可以通过第二个参数判断数组中的值是否存在,如果数值不存在或者是false(假),则返回0

let arr5 = [1,,2,,3,false,true]
Array.from(arr5, n => n || 0);  // [1, 0, 2, 0, 3, 0, true]

Array.fo()

将一组值转换为数组

Array.of(1,2,3);  // [1,2,3]
Array.of(3);   // [3]

find()、findIndex()、findLast()

find()

数组方法,返回符合条件的第一个数组成员,未找到则返回undefined

let fi = [
      {id:1,name:'东方'},
      {id:2,name:'不败'},
      {id:3,name:'东方不败'}
     ]
let back = fi.find(el => el.id == 2)
let back2 = fi.find(el => el.id == 4)
console.log(back);  // {id: 2, name: '不败'}
console.log(back2);  // undefined

findIndex()

数组方法,返回符合条件的数组下标,未找到则返回-1,返回的下标从0开始

let fi2 = [
     {id:1,name:'东方'},
     {id:2,name:'不败'},
     {id:3,name:'东方不败'}
    ]
let back3 = fi2.findIndex(el => el.id == 2)
let back4 = fi2.findIndex(el => el.id == 4)
console.log(back3);  // 1
console.log(back4);  // -1

findLast(

数组方法,从数组尾部开始向前检查,返回符合条件的那一项

     {id:1,name:'东方'},
     {id:2,name:'不败'},
     {id:3,name:'东方不败'}
   ]
let back5 = fi2.findLast(el => el.id == 2)
let back6 = fi2.findLast(el => el.id == 4)
console.log(back5);  // {id: 2, name: '不败'}
console.log(back6);  // undefined

findLastIndex()

数组方法,从尾部开始向前检查,返回符合的当前项的下标,从0号位开始,未找到返回-1

let fi4 = [
    {id:1,name:'东方'},
    {id:2,name:'不败'},
    {id:3,name:'东方不败'}
  ]
let back7 = fi2.findLastIndex(el => el.id == 2)
let back8 = fi2.findLastIndex(el => el.id == 4)
console.log(back7);  // 1
console.log(back8);  // -1

fill()

将给定的参数填充数组

[1,2,3].fill(5);    // [5,5,5]

第二个参数和第三个参数分别为填充的开始位置和结束位置的前一位,从0号位开始

[1,2,3,4,5].fill(9,2,4);    // [1, 2, 9, 9, 5]

这里填充的是从数组的第2号位开始,第4号位的前一位结束


entries()、keys()、values()

keys对键名遍历

for (let index of ['a', 'b'].keys()) { console.log(index) }  // 0  1
• 1

values对键值遍历

for (let index of ['a', 'b'].values()) { console.log(index) } // a  b

entries键值对遍历

for (let [index,item] of ['a', 'b'].entries()) { console.log(index,item) } 
// 0 'a'
// 1 'b

includes()

includes() 判断数组中是否存在对应的值,返回truefalse

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

flat()、flatMap()

flat()

flat()可以将嵌套的数组‘拉平’,变成一维数组

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

flat()的参数代表需要拉平的层数,这里嵌套了3层数组,拉平3

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

Infinity为深度拉平,不管嵌套多少层都会转换为一维数组

[1,2,[3,[4,5,[6,7]]]].flat(Infinity);  // [1, 2, 3, 4, 5, 6, 7]

flatMap()

相当于map函数,对数组的每一项进行迭代操作,并返回新数组,不会影响原数组

[1,2,3].flatMap(el => el + 1);  // [2,3,4]

at()

at()参数为数组的索引

正数从数组头部索引0开始

负数从数组尾部索引 -1 开始,-1代表数组尾部的第一个值

[1,2,3,4,5].at(2);  // 3
[1,2,3,4,5].at(-2); // 4
'hello world'.at(2); // l
'hello world'.at(-3); // r

超出范围返回undefined

[1,2,3,4,5].at(-20); // undefined
[1,2,3,4,5].at(20); // undefined

toReversed()、toSorted()、toSpliced()、with()

普通的数组方法会影响原数组,例如:push()、pop()、shift()、unshift()

现在有一个提案,对数组进行操作时,不影响原数组,返回一个原数组的拷贝

分别有四个:toReversed()、toSorted()、toSpliced()、with()

这四个方法对应的是数组原有的方法,用法一模一样,只是不会改变原数组,返回一个新数组

原数组方法 新数组方法
reverse() toReversed()
sort() toSorted()
splice() toSpliced()
splice( index, 1, value ) with( index, value )

group()、groupToMap()

group() 分组函数,可以将原数组进行分组,并返回分组后的对象,相当于是给符合条件的数组成员取名分组

let gr = [1,2,3,4,5]
let g = gr.group(el=> el > 3 ? 'greater' : 'less')
console.log(g);  // { greater: [4,5], less: [1,2,3] }

groupToMap() 分组函数相当于map函数,对数组的每一项进行迭代操作,并返回新数组,不会影响原数组。


数组空位

数组的空位是指数组的某一个位置没有任何值

console.log(Array(3));  // [empty x 3]也就是[,,,]

需要注意的是,空位并不是undefined,某一个位置的值等于undefined,其实是有值的,空位是没有任何值,in运算符可以直观的看到这一点。

console.log(0 in [undefined,undefined,undefined]);  // true
 console.log(0 in [,,,]);  // false

上面代码说明,第一个数组的0号位是有值的,第二个数组的0号位没有值的


ES5方法对空位的处理是不一致的,但大多数情况下会忽略空位

forEach()、filter()、reduce()、every()、some()都会跳过空位

map()会跳过空位,但会保留这个值

join()toString()会将空位视为undefined,而undefinednull会被处理成空字符串""

ES6则是将空位转换成undefined,ES6的方法不会忽略空位

console.log(Array.from([1,,3]));  //  [1, undefined, 3]
console.log(...[1,,3]);  //  1, undefined, 3

entries()、keys()、values()、find()findIndex()会将空位处理成undefined

es6两个特殊的方法

// copyWithin()会连空位一起复制
console.log([,'a','b',,].copyWithin(2,0));  // [,"a",,"a"]
 // fill会将空位视为正常位
 console.log([4,,6].fill(1));  //  1, 1, 1

js的数组空位处理并不统一,应该避免在数组中出现空位


sort()

sort()排序是数组中一个非常重要的方法

let arr = [2,3,6,4,5,1]
// 升序
console.log(arr.sort((a,b) => a - b));  // [1,2,3,4,5,6]
// 降序
console.log(arr.sort((a,b) => b - a));  // [6,5,4,3,2,1]

按条件排序

let arr2 = [{id:1,name:'名称1'},{id:3,name:'名称3'},{id:2,name:'名称2'},{id:6,name:'名称6'},{id:4,name:'名称4'},{id:5,name:'名称5'}]
let so = arr2.sort((a,b)=>{ return a.id - b.id });
console.log(so);
// [{id: 1, name: '名称1'},{id: 2, name: '名称2'},{id: 3, name: '名称3'},{id: 4, name: '名称4'},{id: 5, name: '名称5'},{id: 6, name: '名称6'}]

关于sort()的详细说明,请看另一篇:sort()排序以及多个属性数组对象排序(按条件排序)


案例源码:https://gitee.com/wang_fan_w/es6-science-institute

如果觉得这篇文章对你有帮助,欢迎点亮一下star哟

目录
相关文章
|
3月前
|
编译器 C# 开发者
C# 11.0中的新特性:覆盖默认接口方法
C# 11.0进一步增强了接口的灵活性,引入了覆盖默认接口方法的能力。这一新特性允许类在实现接口时,不仅可以提供接口中未实现的方法的具体实现,还可以覆盖接口中定义的默认方法实现。本文将详细介绍C# 11.0中接口默认方法覆盖的工作原理、使用场景及其对现有代码的影响,帮助开发者更好地理解和应用这一新功能。
|
4月前
|
网络架构
ES6中数组新增了哪些扩展?
ES6中数组新增了哪些扩展?
42 1
|
4月前
ES6对象新增了哪些扩展?
ES6对象新增了哪些扩展?
34 0
|
4月前
|
网络架构
ES6函数新增了哪些扩展?
ES6函数新增了哪些扩展?
28 0
|
4月前
|
JavaScript 前端开发 索引
es6 数组新增哪些方法以及使用场景
es6 数组新增哪些方法以及使用场景
22 0
|
8月前
|
网络架构
ES6中数组新增了哪些扩展?
ES6通过扩展元素符…,好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列
|
8月前
|
存储 前端开发 JavaScript
ES6新特性。对象、数组新增方法
ES6新特性。对象、数组新增方法
130 0
|
8月前
ES6中对象新增了哪些扩展?
ES6中,当对象键名与对应值名相等的时候,可以进行简写
|
8月前
|
网络架构
ES6中函数新增了哪些扩展?
ES6允许为函数的参数设置默认值
|
10月前
|
网络架构 索引
ES6新增扩展:字符串-数值-数组-函数-对象
ES6新增扩展:字符串-数值-数组-函数-对象
57 0