一、剩余参数和扩展运算符
1. 剩余参数
1.1 剩余参数是什么
- 剩余参数的作用:将传入的参数组合为一个数组,即使没有传值,也会是一个空数组
- 语法:通过
...参数名
定义,使用时直接使用对应参数名即可
const add = (x,y,...args) => {
console.log(args) // [3,4,5,6,7]
}
add(1,2,3,4,5,6,7) //1对应x,2对应y,剩下的会被组合成数组(剩余参数)
1.2 剩余参数的注意事项
- 箭头函数的参数部分即使只有一个剩余参数,也不可以省略圆括号
// 不使用剩余参数时,当只有一个参数可以省略圆括号
const num = x => {
console.log(x)
}
// 当使用了剩余参数,即使只有一个剩余参数,也不可以省略圆括号
const add = (...args) => {
console.log(args)
}
num(1)
add(5,2,3,4)
- 使用剩余参数代替 arguments 获取实际参数
- arguments 是一个
类数组对象
,JS在调用函数时传递的参数就会被 arguments 收集到const fun = function() { console.log(arguments) } fun('嘟嘟',18,'女')
- 箭头函数无arguments对象,可以通过剩余参数来代替
const fun = (...args) => {
console.log(args)
}
fun('嘟嘟',18,'女')
剩余参数只能放在参数列表的最后
,剩余参数的后面不能再有其他参数,否则会报错,剩余参数的前面可以有其他参数
1.3 剩余参数的应用
- 当不明确传入的实参有多少时,可以使用剩余参数接收所有的参数
const add = (...args) => {
let sum = 0
for(let i = 0; i < args.length; i++) {
sum += args[i]
}
return sum
}
console.log(add(8,2,9,10,23,87))
- 剩余参数与解构赋值结合使用(剩余元素)
- 剩余参数不一定要作为函数参数使用
- 不管如何使用,都必须满足:
剩余参数必须位于最后
const [a,...args] = [1,23,13,14,15]
console.log(args)
const {x,y,...args1} = {x:12,y:19,z:829,i:31,j:12}
console.log(x,y,args1)
2. 扩展运算符
- 扩展运算符的作用:合并多个数组或对象
- 有扩展运算符的变量要放最后
- 语法:
...变量名
3. 剩余参数和扩展运算符的区别
- 扩展运算符的作用是展开,剩余参数的作用是聚合
4. 数组的扩展运算符
- 通过扩展运算符将数组展开作为函数参数
function foo(a,b,c) {
console.log(a)
console.log(b)
console.log(c)
}
let arr = [1,2,3]
foo(...arr)
4.1 利用扩展运算符复制数组
const a = [1,2]
const b = a; // 不是复制,是引用
const c = [...a] // 复制
a[0] = 7
console.log(b) // [7, 2]
console.log(c) // [1,2]
4.2 利用扩展运算符合并数组
const ARRAY1 = [1,2,3]
const ARRAY2 = ['a','b']
const ARRAY3 = ['我是数组']
const ARRAY = [...ARRAY1,...ARRAY2,...ARRAY3]
console.log(ARRAY) // [1,2,3,'a','b','我是数组']
4.3 利用扩展运算符将字符串转为数组
console.log([...'你好嘟嘟']) // ['你', '好', '嘟', '嘟']
4.4 利用扩展运算符将类数组转换为数组
- 常见类数组arguments、NodeList
function add() {
console.log([...arguments]);
}
add(2,8,19,10)
5. 对象扩展运算符
- 对象必须写在 {} 中进行展开
5.1 扩展运算符复制对象
const person = {
name:'嘟嘟',
age:19,
sex:'女'
}
console.log({...person}) // {name: '嘟嘟', age: 19, sex: '女'}
5.2 扩展运算符合并对象
- 属性同名时,后面的属性会覆盖前面的
const person = {
name:'嘟嘟',
age:19,
sex:'女'
}
const person1 = {
age:18,
hobby:'游泳'
}
console.log({...person,...person1}) //{name: '嘟嘟', age: 18, sex: '女', hobby: '游泳'}
5.3 空对象的展开
- 空对象的展开没有任何效果,得到的也是个空对象
console.log({...{}}) // {}
console.log({...{},name:'dudu '}) // {name: 'dudu '}
5.4 非对象的展开
- 展开的如果不是对象,会自动转为对象,再将属性罗列出
- 展开的如果是字符串,会被转换为类数组对象,其他的非对象展开会得到一个空对象
console.log({...true,...9}) // {}
console.log({...'dudu'}) // {0: 'd', 1: 'u', 2: 'd', 3: 'u'}
5.5 对象中对象属性的展开
- 展开运算符不会展开对象中的对象属性
const person = {
name:'嘟嘟',
age:19,
sex:'女',
hobby: {
sport:'游泳'
}
}
console.log({...person}) // {name: '嘟嘟', age: 19, sex: '女', hobby: {…}}
二、 Set 和 Map 数据结构
1. Set
1.1 set是什么
- set 是一系列无序的、没有重复值的数据集合
- set 只能通过实例化构造函数来创建
- set 中不能有重复成员
- set 中没有下标去标识每一个值,所以set 是无序的,不能通过数组的下标方法去访问元素
const s = new Set()
s.add(1)
s.add(2)
s.add(1)
console.log(s) // Set(2) {1, 2}
1.2 set实例的方法和属性
add()
:给set添加成员- 可以连续通过.add() 添加多个成员
const s = new Set()
s.add(1).add(2).add(4).add(3)
console.log(s) // Set(4) {1, 2, 4, 3}
has()
:判断set中是否含有某个成员,如果有返回true,如果没有返回false
const s = new Set()
s.add(1).add(2).add(4).add(3)
console.log(s.has(2)) // true
console.log(s.has(8)) // false
delete()
:删除指定成员- 当删除一个不存在的成员时,也不会报错
clear()
:清空set(删除所有成员)
const s = new Set()
s.add(1).add(2).add(4).add(3)
s.delete(1)
console.log(s); // Set(3) {2, 4, 3}
s.clear()
console.log(s); // Set(0) {size: 0}
forEach()
遍历set,是访问set成员的方式- forEach 是按照成员添加的顺序进行遍历的
- 第一个参数为回调函数,该回调函数有两个参数value、key,其中value和key的值相同。该回调函数的第三个参数为set,set的值就为该set实例
- 第二个参数指定this的指向
const s = new Set()
s.add(1).add(2).add(4).add(3)
s.forEach((value,key,set) => {
console.log(value)
})
size属性
:类似于数组length,用于获取set成员的个数
const s = new Set()
s.add(1).add(2).add(4).add(3)
console.log(s.size) // 4
1.3 set 构造函数的参数
- 可以传递的值:数组、字符串、arguments、NodeList、set实例等
console.log(new Set([1,2,3,1,2])) // Set(3) {1, 2, 3}
console.log(new Set('dudu')) // Set(2) {'d', 'u'}
function fun() {
console.log(new Set(arguments)) // Set(3) {'dudu', 18, '女'}
}
fun('dudu',18,'女')
- 当传递的是一个set实例时,就相当于复制了set实例
1.4 set 的注意事项
1.4.1 set 判断重复的形式
- set 对重复值得判断基本遵循严格相等(===)
- 但set在判断NaN时与 === 不同,set中 NaN 等于 NaN
console.log(new Set([NaN,1,2,NaN])) // Set(3) {NaN, 1, 2}
1.4.2 set 应用场景
- 数组或者字符串去重
/**
* 数组去重
*/
// 需要去重的数组
const array = [1,2,1,2,5,87,2,5,0,10,9,5]
// 通过set去重
const s = new Set(array)
// 展开为去重后的新数组
const list = [...s]
console.log(list)
/**
* 字符串去重
*/
const str = 'hellohello'
const s = new Set(str)
const str1 = [...s].join('')
console.log(str1) // helo
- 当不需要通过下标访问,只需要遍历时
// 操作DOM
const pList = document.querySelectorAll('p')
const s = new Set(pList)
s.forEach(elem => {
console.log(elem)
})
- 当需要使用set的方法或属性时
2. Map
2.1 map 是什么
- Map 和 对象都是键值对的集合
- map只能通过new构造函数的形式创建
- 对象的键一般是字符串(一般不写引号)
- map的键可以使用任意类型
2.2 map 实例的方法和属性
2.2.1 set方法
set()
添加成员,可以是连缀的写法- set 添加的成员是键值对形式
const m = new Map()
m.set('name','dudu').set(true,true).set(new Set([12,32]),[27,19]) // Map(3) {'name' => 'dudu', true => true, Set(2) => Array(2)}
- 使用set添加的成员,如果键已经存在,则后添加的会覆盖已有的
2.2.2 get方法
get()
通过键名获取map成员
const m = new Map()
m.set('name','dudu').set(true,true).set(new Set([12,32]),[27,19])
console.log(m.get('name')) // dudu
- 如果获取不存在的map成员,会返回 undefined
2.2.3 has 方法
- has() 判断是否含有指定键
const m = new Map()
m.set('name','dudu').set(true,true).set(new Set([12,32]),[27,19])
console.log(m.has('name')) // true
2.2.4 delete 方法 和clear方法
- delete() 通过键名删除某个成员
- clear() 清空map
const m = new Map()
m.set('name','dudu').set(true,true).set(new Set([12,32]),[27,19])
m.delete(true)
console.log(m); // Map(2) {'name' => 'dudu', Set(2) => Array(2)}
m.clear()
console.log(m); // Map(0) {size: 0}
2.2.5 forEach 方法
- forEach() 接收两个参数
- 第一个参数是必选的,是一个回调函数,该回调函数可以接收三个参数:value、key、mapObj
- 第二个参数用于改变this指向
2.2.6 size属性
- 用于获取map中的成员个数
2.3 map 构造函数的参数
- 可以传递的值:数组(二维)、set、map等
- 传递数组必须是二维数组
- 所传的参数要体现出键和值
- 传递一个map时,相当于复制map
// 传数组
console.log(new Map([
['name','dudu'],
['age',19]
])) // Map(2) {'name' => 'dudu', 'age' => 19}
// 传set
const s = new Set([
['name','dudu'],
['age',19]
])
console.log(new Map(s)) // Map(2) {'name' => 'dudu', 'age' => 19}
// 传map
const m = new Map([
['name','dudu'],
['age',19]
])
console.log(new Map(m)) // Map(2) {'name' => 'dudu', 'age' => 19}
2.4 map 的注意事项
2.4.1 map 判断键名是否相同的方式
- 基本遵循严格相等(===),但map中 NaN 等于 NaN
2.4.2 map 的使用场景
- 如果只是需要 key:value的结构,或者需要字符串以外的值做键,使用Map更适合
三、遍历器
1. Iterator
- Iterator :遍历器(迭代器)
- Iterator本质是一个指针对象,其中包含一个next方法,这个方法可以改变指针的指向,并且返回一个包含value和done的对象,value为当前所指向的成员的值,done表示是否遍历完成
- Iterator 是一个遍历过程:可遍历对象的生成方法 ==》 可遍历对象 ==》 调用next()方法 ==》 调用next 方法直到返回done为止
- 一般不会直接使用 Iterator,而是进行封装后使用,如 for … of
2. for … of
- 遍历数组的方法,只会遍历出done为false时的value值
- for …of 可以和 break、continue搭配使用
- for…of不能获取索引
const array = [1,2,3,4,5,6]
for(const item of array) {
if(item === 5) break
console.log(item);
}
- values() 遍历健值,和直接for … of 效果一样
- keys() 获取索引
const array = [1,2,3,4,5,6]
for(const key of array.keys()) {
console.log(key)
}
- entries() 索引+值 组成的可遍历对象
const array = [1,2,3,4,5,6]
for(const item of array.entries()) {
console.log(item)
}
3. 原生可遍历和非原生可遍历
可遍历
:有Symbol.iterator方法,并且该方法可生成可遍历对象- 只要是可遍历的,就可以使用 for…of 进行遍历
原生可遍历
的:数组、字符串、Set、Map、arguments、NodeList非原生可遍历
:一般对象
四、ES6的新增方法
1. 字符串的新增方法
1.1 startsWith()、endsWith()、includes()
- 作用:判断一个字符串是否包含在另一个字符串中
includes()
:返回布尔值,表示是否找到了参数字符串startsWith()
:返回布尔值,表示参数字符串是否在查找字符串的头部;endsWith()
:返回布尔值,表示参数字符串是否在查找字符串的尾部。
let str = '嘟嘟是只萨摩耶!'
console.log(str.endsWith('!')) //true
console.log(str.startsWith('萨摩耶!')) //false
console.log(str.includes('是'))// true
includes()
可以接收第二个参数,表示开始搜索的位置,默认是0
1.2 padStart()、padEnd()
- 作用: 补全字符串长度
padStart()
用于头部补全padEnd()
用于尾部补全- 一共接受两个参数,第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串
let str1 = '嘟嘟';
let str2 = str1.padEnd(6,'今年四岁!') //在‘嘟嘟’的尾部补全6个字符串
console.log(str2) //嘟嘟今年四岁
let str3 = str1.padStart(6,'胖狗狗是') //头部补全6个字符串
console.log(str3) // 胖狗狗是嘟嘟
let str4 = str1.padEnd(9,'今年四岁!')
console.log(str4) // 嘟嘟今年四岁!今年
- 如果原字符串长度大于等于要补全的长度时,不会去消减原字符串,而是直接返回原字符串
let str = '嘟嘟是只萨摩耶!'
console.log(str.padEnd(3,'哈哈')) // 嘟嘟是只萨摩耶!
- 用来补全的字符串与原字符串长度超过了设置的最大长度,则会截取补全字符串的超出部分,而不会去截取原字符串
let str = '123'
console.log(str.padStart(10,'abcdefghijkl')) // abcdef123
- 如果没有设置补全字符串,则默认使用空格补全
应用场景
- 显示日期格式
1.3 trimStart()、trimEnd()、trim()
- 作用:清除字符串首或尾空格,中间的空格不会被清除
- trim() 同时清除首和尾的空格
应用场景
- 表单输入
1.4 repeat()
- repeat(str,num) 方法返回一个新字符串,表示将原字符串重复n次
- str:需要重复的字符串
- num:要重复的次数,次数不可以为负数
let str = '哈',
str1 = str.repeat(5) // 将‘哈’重复5遍
console.log(str1) //哈哈哈哈哈
2. 数组的新增方法
2.1 Array.includes()
- includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似
const array = [1,2,3,4]
console.log(array.includes(2)) // true
应用场景
- 数组去重
2.2 Array.from()
- 作用:将其他类型转换为数组
- 所有可遍历的:数组、字符串、Set、Map、arguments、NodeList,都可以通过Array.from()转为数组,但更推荐使用展开运算符直接转换
- Array.from()更常用于将一个类数组对象或者可遍历对象转换成一个真正的数组(将伪数组转换为数组)
类(伪)数组:按照索引方式传数据,且 必须具有length属性
let arrayLike = {
'0':'嘟嘟',
'1':18,
'2':'女',
length:3 //必须加上!!!
}
let arr = Array.from(arrayLike)
console.log(arr) // ['嘟嘟', 18, '女']
Array.ffrom(arrayLike,mapFn,thisArg)
第一个参数(必选):类(伪)数组,
第二个参数(可选):遍历函数,类似于数组的Map方法,用于对每个元素进行处理,返回最终处理后的数组
第三个参数(可选):修改this指向,如果要指定第三个参数,则第二个参数不能使用箭头函数
console.log(Array.from('1234',(val)=>{
return val * 2
})) // [2,4,6,8]
数组的 map方法
- map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
- map() 方法按照原始数组元素顺序依次处理元素。
- map() 不会对空数组进行检测。
- map() 不会改变原始数组
2.3 find()、findIndex()
find()
:查找第一个
符合条件的数组成员,它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefinedfindIndex()
:返回第一个
符合条件的数组成员的位置(索引)
,如果所有成员都不符合条件,则返回-1- find()、findIndex()的回调函数可以接受
三个参数
,依次为当前的值、当前的位置和原数组
const array = [0,19,28,3,4,12,3]
console.log(array.find((val,index,arr) => {
return val>20
})) // 28
2.4 Array.fill()
- fill() :使用给定值,填充一个数组
Array.fill(value,start,end)
let array = Array(5).fill('hello!')
console.log(array) // ['hello!', 'hello!', 'hello!', 'hello!', 'hello!']
let arr = Array(5).fill(4,0,5)
console.log(arr) //(5) [4, 4, 4, 4, 4]
let array1 = [1,2,3,4,5,6]
// 将5,6替换成7
let newArr = array1.fill(7,4,6) // (6) [1, 2, 3, 4, 7, 7]
console.log(newArr)
2.5 keys()、values()、entries()
- entries(),keys()和values()——用于遍历数组。它们都返回一个遍历器对象,可以用for…of循环进行遍历
- keys()是对键名的遍历
- values()是对键值的遍历
- entries()是对键值对的遍历
const array = ['嘟嘟',4,'女']
// 获取键
for(const key of array.keys()) {
console.log(key)
}
// 获取值
for(const value of array.values()) {
console.log(value)
}
// 获取键值对
for(const [key,value] of array.entries()) {
console.log(key,value)
3. 对象的新增方法
3.1 Object.assign()
- 合并对象,第一个参数为要返回的对象(目标对象),其余参数为要合并的对象(源对象)
- 该方法的效果和扩展运算符的效果相同,但assign是把后一个对象合并到前一个对象,而扩展运算符是返回一个新对象。
- 在合并时,如果有同名的键,则后面的会覆盖前面的
const dog = {
name:'嘟嘟',
age:4,
sex:'女',
hobby:['游泳']
}
const cat = {
name:'傻猪',
age:1,
sex:'男',
type:'cat'
}
// 扩展运算符
console.log({...cat,...dog}) // {name: '嘟嘟', age: 4, sex: '女', type: 'cat', hobby: Array(1)}
// Object.assign()
console.log(Object.assign(cat,dog)) // {name: '嘟嘟', age: 4, sex: '女', type: 'cat', hobby: Array(1)}
console.log(cat) // {name: '嘟嘟', age: 4, sex: '女', type: 'cat', hobby: Array(1)}
- 如果要使用assign 返回一个新对象,可以将第一个参数设置为空对象
- 基本数据类型作为源对象,与对象的展开类似,先转换为对象,再合并
应用场景
- 合并默认参数和用户参数
const logUser = userOptions => {
const DEFAULTS = {
userName:'张三',
age:0,
sex:'男'
}
// 如果传了参数,就使用传递的参数,否则使用默认参数
const options = Object.assign({},DEFAULTS,userOptions)
console.log(options)
}
const dog = {
userName:'嘟嘟',
age:4,
sex:'女',
hobby:['游泳']
}
logUser(dog)
3.2 Object.is()
- 用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。但在Object.is()中,+0不等于-0,NaN等于NaN
3.3 Object.keys()、Object.values()、Object.entries()
- 用法和数组类似方法相同
- Object.keys() 用于获取对象自身所有可枚举的属性,返回一个由属性名组成的数组
- Object.values() 获取对象自身所有可枚举的属性值,返回一个由属性值组成的数组
- Object.entires() 遍历并返回该对象可枚举属性的键值对数组,返回对象可枚举属性的键值对数组
- 与数组类似方法的区别
- 调用方式不同,数组中是通过实例对象调用方式,如
数组.keys()
;而对象中是通过构造函数调用,如Object.keys(对象)
- 返回的内容不同,对象的这三个方法返回都是数组,而2数组的这三个方法返回的都是 interator
- 调用方式不同,数组中是通过实例对象调用方式,如
const dog = {
userName:'嘟嘟',
age:4,
sex:'女'
}
console.log(Object.keys(dog))
console.log(Object.values(dog))
console.log(Object.entries(dog))
const array = ['嘟嘟',4,'女']
console.log(array.keys())
console.log(array.values())
console.log(array.entries())
4. 数值的新增方法
4.1 Number.parseInt()、Number.paseFloat()
Number.parseInt()
:解析一个字符串,并返回一个整数
- 只有字符串中的第一个数字会被返回。
- 开头和结尾的空格是允许的。
- 如果字符串的第一个字符不能被转换为数字,那么 parseInt() 会返回 NaN
console.log(Number.parseInt('w2s28ww72.3hh')) // NaN
console.log(Number.parseInt('232hs')) // 232
console.log(Number.parseInt('6.9')) // 6
Number.paseFloat()
:解析一个字符串,并返回一个浮点数
- 字符串中只返回第一个数字。
- 开头和结尾的空格是允许的。
- 如果字符串的第一个字符不能被转换为数字,那么 parseFloat() 会返回 NaN
console.log(Number.parseFloat('s21.1')) // NaN
console.log(Number.parseFloat('2.912')) // 2.912
4.2 Number.isNaN()
- 判断一个值是否为NaN,如果参数类型不是NaN,Number.isNaN一律返回false
console.log(Number.isNaN(NaN)) // true
console.log(Number.isNaN(Number.parseFloat('s21.1'))) // true
console.log(Number.isNaN('292')) // false
console.log(Number.isNaN(true)) // false
4.3 Number.isFinite()
- 判断一个数值是否为有限的(finite)
- 该方法不会强制将一个非数值的参数转换成数值
- 只有数值类型的值,且是有穷的(finite),才返回 true
- 否则一律返回false
console.log(Number.isFinite(2/0)) //false
console.log(Number.isFinite(1223)) //true