ES6入门之数组的扩展

简介: ES6入门之数组的扩展

1. 扩展运算符

...表示,将一个数组转为用逗号分隔的参数序列,如下:

console.log(...[1,2,3]) // 1 2 3
console.log(1, ...[2,3,4], 5) // 1 2 3 4 5
[...document.querySelectorAll('div')] // [
, 
, 
]
function add(x, y){
return x + y
}
const n = [3, 5]
add(...n) // 8
扩展运算符可以和正常函数结合使用,如下:
function f(a,b,c,d,e){
console.log(a,b,c,d,e)
}
const age = [0,1]
f(-1,...age,2,...[3]) // -1 0 1 2 3
扩展运算符后面也可以是表达式,如下:
const x = 10
const arr = [
    ...(x > 0 ? ['a'] : []), 'b',
]
arr // ['a', 'b']
重要:如果扩展运算符后面是一个空数组,将不会有任何效果。另外只有在函数调用的时候扩展函数在放在圆括号之内,其他的则会报错。
替代函数的apply方法

扩展函数可以展开数组,所以将不需要apply方法来将数组转换为函数的参数。

function f(x, y, z){
console.log(x, y, z)
}
var a = [1,2,4]
// ES5 
f.apply(null, args)
// ES6
f(...a)
// Math.max方法
//ES5
Math.max.apply(null, [14, 3, 99])
//ES6
Math.max(...[12, 4, 55])
//等同于
Math.max(12, 4, 55)
// push方法的应用
var a = [0,1,2]
var b = [3,4,5]
//ES5
Array.prototype.push.apply(a,b) // 0,1,2,3,4,5
//ES6
a.push(...b)
扩展运算符的应用
  1. 复制数组
因为数组是复合的数据类型,直接的复制只是复制数组在堆内存中的指针地址
const a1 = [1,2]
const a2 = a1
a2[0] = 3
a1 // [3,2]
// ES5 通过变通方法来复制
const a1 = [1,2]
const a2 = a1.concat()
a2[0] = 23
a1 // [1,2]
// ES6写法
const b1 = [1,3]
const b2 = [...b1] or [...b2] = b1
  1. 合并数组
const a1 = ['b', 'c']
const a2 = ['d']
const a3 = ['x', 'y']
// ES5中合并数组
a1.concat(a2, a3)
// ES6中合并数组
[...a1, ...a2, ...a3]
//以上两种都是浅拷贝,修改原数组和同步新数组
  1. 与解构赋值一起使用,扩展只能放在最后一位,不然会报错
// ES5
a = list[0], rest = list.slice(1)
// ES6
[a,...rest] = list
// 其他
const [a,...c] = [1,2,4,5,4,6] // a 1   c 2,4,5,4,6
const [a,...c] = [] // a undefined   c []
const [a,...c] = ['a'] // a 'a'   c []
  1. 字符串,将字符串转换为数组
[...'hello'] // [h,e,l,l,0]
  1. 实现了Iterator接口的对象
任何定义了遍历器接口对象,都可以用扩展运算符转为真正的数组
let nodelist = document.querySelectorAll('div')
let array = [...nodelist]
// querySelectorAll 返回的是一个类数组,通过扩展运算符
将其转换为一个真正的数组
  1. Map 和 Set 解构,Generator函数
扩展运算符调用的是数据解构的Iterator接口,只要有Iterator接口的
对象,都可以使用扩展运算符
// Map
let map = new Map([
    [1, 'a'],
    [2, 'b'],
    [3, 'c'],
])
let arr = [...map.keys()] // 1, 2, 3
let arr = [...map.values()] // 'a', 'b', 'c'
//Generator函数
const go = function*(){
yield 1;
yield 2;
yield 3;
}
[...go()] // [1, 2, 3]

2. Array.from()

Array.from 方法用于将两类对象转为真正的数组。1、类似数组对象 和 可遍历的对象(包裹Set和Map),如下:

let arrLike = {
'0': 'a',
'1': 'b',
'2': 'c',
    length: 3
}
// ES5 
var a1 = [].slice.call(arrLike)
// ES6
var a2 = Array.from(arrLike)

在实际中,像获取dom后返回的Nodelist集合,以及函数内部的arguments对象就是类数组,通过 Array.from将它们转换为真正的数组。

// NodeList 对象
let ps = document.querySelectorAll('p')
Array.from(ps).filter(p => {
return p.textContent.length > 100
})
// arguments 对象
function foo(){
var arg = Array.from(arguments)
}
// 只要部署了Iterator接口的数据解构,Array.from都能将其转成数组
Array.from('hello') // ['h', 'e', 'l', 'l', 'o']
let nl = new Set([1, 2])
Array.from(nl) // [1, 2]
// 如果是真数组则返回一样的
Array.from([1, 2, 3]) // [1, 2, 3]

... 扩展运算符也可以将某些类数组转换为数组,如arguments和NodeList集合

拥有lenght属性的对象都可以通过Array.from转换为数组,而扩展运算符则不行。

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

对于低版本的浏览器,可以通过 Array.prototype.slice 方法替代

Array.from 还可以接受第二个参数如同map一样,用来对每个元素进行操作,并将处理后的值放入返回的数组中。

const arrlike = new Set([1,2,3])
Array.from(arrlike, x => x * x)   // =
Array.from(arrlike).map(x => x * x)   // [1, 4, 9]
//注意: 如果map中用到了this,可以传入Array.from
的第三个参数,用来绑定this

Array.from 可以将各种值转换为真正的数组,并且还提供map相关功能,这样代表如果有个原始数据结构,可以先将他转换为数组,然后使用数组相关的方法。

3. Array.of()

用于将一组值,转换为数组。主要用来弥补Array函数因为参数个数不同而导致的差异

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

4. 数组的实例 copyWithin()

将当前数组中指定位置的元素复制到另外一个位置,并且会覆盖那个位置的原有元素,会修改当前数组

// 有三个参数
1. target(必须):从该位置开始替换数据,如果是负值,则倒数
2. start(可选):从该位置读取数据,默认0,负值同上
3. end(可选):到这个位置停止读取数据,默认等于数组长度,负值同上
let p = [1,2,3,4,5,6,7]
p.copyWithin(0,5,7)
[6, 7, 3, 4, 5, 6, 7]

5. 数组实例的 find() 和 findIndex()

find 用来找出数组中符合条件的成员,它的参数是一个回调函数,找到一个返回值为true的返回,如果没有则返回undefined

let s = [1,2,3,4,5,6]
s.find(x => x > 4)
// 5
find 方法的回调函数有三个参数
    value // 当前值
    index // 当前的位置
    arr // 原数组

findIndex 同find方法类似,只不过都不符合返回的是 -1,而且符合是返回符合条件值的位置而不是值。

let s = [1,2,3,4,5,6]
s.find(x => x > 4)
// 4

find 和 findIndex 都可以接受第二个参数

function o(p){
return p > this.age
}
const u = {name: 'cx', age: 11}
const y = [8,11,22,2,4]
y.find(o, u) // 22  返回的值
y.findIndex(o, u) // 2  返回值的位置

6. 数组实例的 fill()

通过给定值,填充一个数组

let sz = [1,2,3,4,5,6]
sz.fill(1) // [1,1,1,1,1,1]
sz.fill(1,0,3) 
// 接受三个参数,第一个为填充值,第二个为起始位置,第三个为截至位置
sz.fill(1,3)
// 如果省略最后一个参数,则默认从起始位置到数组默认长度结束

7. 数组实例的 entries(), keys(), values()

三种方法主要用于遍历数组,可以用 for...of...进行遍历,keys()对应键名,values对应键值,entries()对键值对的遍历

let bo = ['a', 'c']
for(let r of bo.keys()){
console.log(r) // 0 1
}
// 0 1
for(let n of bo.values()){
console.log(n) 
}
// a c
for(let s of bo.entries()){
console.log(s)
}
// [0, "a"]
// [1, "c"]

8. 数组实例的 includes()

用来表示某个数组是否包含给定的值,返回一个布尔值

let i = ['a',1,2,3]
i.includes()  // false
i.includes(1) // true
i.includes(10) // false

indexOf 和includes 的区别

indexOf // 不够语义化,它的作用是找到参数出现的第一个位置,
所以要比较是否为 -1,另外由于 内部使用的是 ===  则导致NaN
的误判。
// [NaN].indexOf(NaN) // -1
includes // 使用的是不一样的算法,则不会有这个问题
// [NaN].includes(NaN) // true

Map 和 Set 的has 方法和includes的区别

Map 的has 方法是用来查找键名的
Set 的has 方法是用来查找值的

9. 数组的实例 flat(), flatMap()

flat() 将嵌套的二维数组变成一维数组,如果需要拉平多维数组,则flat(多维数量) 或者使用 Infinity 直接转为一维数组

let rw = [1,2,3,[4,5,6],7]
rw.flat()  // [1, 2, 3, 4, 5, 6, 7]
let dw =  [1,2,3,[4,5,6,[7,8],[2,['a','b'],4,5]],[5,6,]]
dw.flat(3) // [1, 2, 3, 4, 5, 6, 7, 8, 2, "a", "b", 4, 5, 5, 6]
// 如果你不知道是多少层嵌套而都想转成一维,可以使用 Infinity
dw.flat(Infinity) 
// [1, 2, 3, 4, 5, 6, 7, 8, 2, "a", "b", 4, 5, 5, 6]

flatMap() 对数组执行map,然后对返回值组成的数组 执行flat,不会改变原数组。flatMap只能展开一层数组。

let mp = [2,3,4,5]
mp.flatMap((item) => [item, item* 2])
// [2, 4, 3, 6, 4, 8, 5, 10]
====
mp.map((item) => [item, item*2])
// [[2,4],[3,6],[4,8],[5,10]]
mp.flat()
// [2, 4, 3, 6, 4, 8, 5, 10]

10. 数组的空位(避免出现空位)

数组的空位指的是该数组中某一个位置没有任何值。另外空位不是undefined,如果一个位置的值是undefined,那么这个位置还是有值的。

Array(3) // [, , ,]

ES5中大多数情况中对待空位都是会忽略

- forEach(), filter(), reduce(), every() 和 some() 都会跳过空位
- map() 跳过但保留这个值
- join() 和 toString() 中 空位 === undefined,而 undefined和null会被处理成空字符串

ES6 中 空位则转换为undefined

- Array.from([1,,2]) // [1, undefined, 2]
- [...['a',,'b']]    // [ "a", undefined, "b" ]
entries()
keys()
values()
find()
findIndex()  // 都会将空位处理成undefined。
相关文章
|
7月前
|
JSON 自然语言处理 JavaScript
ES6 字符串的扩展
ES6 字符串的扩展
|
2月前
|
前端开发 网络架构
ES6对函数做了哪些扩展?
本文首发于微信公众号“前端徐徐”,介绍了 ES6 中函数参数的默认值、rest 参数、严格模式、name 属性、箭头函数、尾调用优化等新特性,并详细解释了各个特性的使用方法和注意事项。同时,还介绍了 ES2017 和 ES2019 中关于函数的一些改进,如函数参数尾逗号、`Function.prototype.toString()` 方法的修改以及 `catch` 语句参数的省略。
21 1
|
7月前
|
Serverless 网络架构
ES6学习笔记--函数与数组的拓展
ES6学习笔记--函数与数组的拓展
|
自然语言处理 JavaScript 前端开发
ES6(字符串的扩展)
ES6(字符串的扩展)
100 0
|
网络架构
ES6学习(五)—数组的扩展
ES6学习(五)—数组的扩展
|
网络架构
ES6学习(六)—函数的扩展
ES6学习(六)—函数的扩展
|
网络架构
es6扩展运算符的学习使用
es6扩展运算符的学习使用
53 0
ES6 从入门到精通 # 08:扩展的对象的功能
ES6 从入门到精通 # 08:扩展的对象的功能
80 0
ES6 从入门到精通 # 08:扩展的对象的功能
|
JavaScript 前端开发
【ES6】数组的拓展
【ES6】数组的拓展