ES6入门之数组的扩展

栏目: JavaScript · 发布时间: 5年前

内容简介:...表示,将一个数组转为用逗号分隔的参数序列,如下:重要:如果扩展运算符后面是一个空数组,将不会有任何效果。另外只有在函数调用的时候扩展函数在放在圆括号之内,其他的则会报错。扩展函数可以展开数组,所以将不需要apply方法来将数组转换为函数的参数。
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')] // [<div>, <div>, <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
    复制代码
  2. 合并数组

    const a1 = ['b', 'c']
     const a2 = ['d']
     const a3 = ['x', 'y']
     
     // ES5中合并数组
     a1.concat(a2, a3)
     
     // ES6中合并数组
     [...a1, ...a2, ...a3]
    
     //以上两种都是浅拷贝,修改原数组和同步新数组
    复制代码
  3. 与解构赋值一起使用,扩展只能放在最后一位,不然会报错

    // 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 []  
    复制代码
  4. 字符串,将字符串转换为数组

    [...'hello'] // [h,e,l,l,0]
    复制代码
  5. 实现了Iterator接口的对象

    任何定义了遍历器接口对象,都可以用扩展运算符转为真正的数组
    
     let nodelist = document.querySelectorAll('div')
     let array = [...nodelist]
     // querySelectorAll 返回的是一个类数组,通过扩展运算符
     将其转换为一个真正的数组
    复制代码
  6. 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。
复制代码
ES6入门之数组的扩展

欢迎关注 公众号【小夭同学】

ES6入门系列

ES6入门之let、cont

ES6入门之变量的解构赋值

ES6入门之字符串的扩展

ES6入门之正则的扩展

ES6入门之数值的扩展

ES6入门之函数的扩展

Git教程

前端Git基础教程


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Uberland

Uberland

Alex Rosenblat / University of California Press / 2018-11-19 / GBP 21.00

Silicon Valley technology is transforming the way we work, and Uber is leading the charge. An American startup that promised to deliver entrepreneurship for the masses through its technology, Uber ins......一起来看看 《Uberland》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具