一、剩余参数与展开运算符
1.剩余参数
剩余参数永远是个数组,即使没有值,也是空数组
const add=(x,y,z,...args)=>{};
1.1注意事项
a.箭头函数的剩余参数
箭头函数的参数部分即使只有一个剩余参数,也不能省略圆括号
b.使用剩余参数替代arguments获取实际参数
const add=function(){
console.log(arguments);
};
add(1,2)
//箭头函数没有arguments
//arguments是类数组,剩余参数是数组
const ada=(...args)=>{
console.log(args);
}
ada(1,2)
c.剩余参数的位置
剩余参数只能是最后一个参数,之后不能再有其他参数,否则会报错
1.2剩余参数的应用
a.
const add=(...args)=>{
let sum=0;
for(let i=0;i<args.length;i++){
sum+=args[i];
}
return sum;
}
console.log(add(1,2,3))
b.与解构赋值结合使用
//剩余参数不一定非要作为函数参数使用
const [num,...args]=[1,2,3,4]
console.log(num,args)
//
const {x,y,...z}={a:3,x:1,y:2,b:4}
console.log(x,y,z)
2.数组的展开运算符(...)
2.1数组展开运算符的基本用法
console.log(Math.min(1,2,3))
//等价于
console.log(Math.min(...[1,2,3]))
2.2区分剩余参数和展开运算符
//剩余参数
1,2,3->[1,2,3]
//展开运算符
[1,2,3]->1,2,3
const add=(...args)=>{
console.log(args);
console.log(...args);
};
add(1,2,3)
2.3数组展开运算符的运用
2.3.1复制
//复制
const a=[1,2]
const b=a
a[0]=3
console.log(b)
//b数组跟着a数组的变化而变化
const c=[...a]
a[0]=4
console.log(c)
console.log(a)
2.3.2合并数组
//合并数组
const a=[1,2]
const b=[1,5,3,7]
const c=[..a,..b]
const d=[...c,10,15,..a]
2.3.3字符串转换为数组
//字符串可以按照数组的形式转换
console.log(..."Alex")
//等价于
console.log("A","l","e","x")
console.log([..."Alex"])
2.3.4类数组转化为数组(arguments,nodelist)
2.4对象的展开运算符
2.4.1基本用法:
a.对象不能直接展开,必须在{}中展开
b.对象的展开:把属性罗列出来,用逗号隔开,放到一个{}中,构成新对象
c.合并对象:新对象拥有全部属性,相同属性,后者覆盖前者
2.4.2注意事项
a.空对象的展开,则没有任何效果
b.非对象的展开:如果展开的不是对象,则会自动将其转为对象,在将属性罗列出来;如果展开运算符后面是字符串,他会自动转成一个类似数组的对象,因此返回的不是空对象
c.对象中对象属性的展开:不会展开对象中的对象属性(合并:后面的覆盖前面的,而不是和前面的合并(相同属性覆盖,不同属性留下))
const apple={
feature:{
taste:"甜"
}
};
const pen={
feature:{
color:"黑色",
shape:"圆柱形"
},
use:"写字"
}
console.log({...apple})//不会展开对象中的对象属性
console.log({...apple,...pen})//后面的覆盖前面的,不是合并
//result:
//{feature:{
color:"黑色",
shape:"圆柱形"
},
use:"写字"
}
2.4.3对象展开运算符的运用
a.复制对象
const b={x:1,y:2}
const a={...b}
b.用户参数和默认参数
二、Set和Map数据结构
1.Set数据结构
1.1Set是一系列无序、没有重复值的数据集合(Set没有下标去标示每一个值,所以Set是无序的),数组是有序集合。
1.2Set中不能有重复的成员
const s=new Set([1,2,1])
s.add(3).add(5).add(6)
console.log(s)
1.3Set的实例方法和属性
//一、方法
//1.add
const s=new Set();
s.add(1).add(2)
//2.has:检查集合中是否存在这个成员
console.log(s.has(1))
//3.delete:删除指定的成员,当删除不存在的成员时,什么都不会发生,也不会报错
s.delete(1)
//clear:清除集合中的所有成员
s.clear();
//forEach:遍历每个成员(按照成员添加进集合的顺序遍历)
s.forEach(function(value,key,set){
//Set中value=key
console.log(value,key,set===s)
console.log(this)
},document)
//二、属性
//size
console.log(s.size)
1.4Set的注意事项
1.4.1Set对重复的判断基本遵循严格相等(===),但是对于NaN的判断与===不同,Set中的NaN等于NaN
1.4.2什么时候使用Set
a.数组或字符串去重时
b.不需要通过下标访问,只需要遍历时
c.为了使用Set提供的方法和属性时(add delete clear has forEach size 等)
1.5Set的应用
1.5.1数组去重
[1, 2, 1];
const s = new Set([1, 2, 1]);
console.log(s);
s.forEach
console.log(...s);
console.log([...s]);
console.log([...new Set([1, 2, 1])]);
1.5.2字符串去重
'abbacbd';
const s = new Set('abbacbd');
console.log([...s].join(''));
console.log(s);
console.log([...new Set('abbacbd')].join(''));
1.5.3存放DOM元素
console.log(document.querySelectorAll('p'));
for()
const s = new Set(document.querySelectorAll('p'));
console.log(s);
s.forEach(function (elem) {
// console.log(elem);
elem.style.color = 'red';
elem.style.backgroundColor = 'yellow';
});
2.Map数据结构
1.1Map和对象都是键值对的集合
const m=new Map()
m.set('name','alex')
console.log(m)
1.2Map和对象的区别
1.2.1:对象一般用字符串当作键
const obj={
name:'alex',
age:18,
}
//由于name和age是正确的标识符,所以可以取掉引号
1.2.2:Map的键的类型
基本数据类型:数字、字符串、布尔值、undefined、null
引用数据类型:对象([]、{}、函数、Set、Map等)这两种数据类型都可以作为Map的键。
1.3Map的注意事项
1.3.1判断键名是否相同的方式:基本遵循严格相等(===),列外就是NaN,Map中NaN也是等于NaN
console.log(NaN===NaN)
const m=new Map()
m.set(NaN,1).set(NaN,2)
console.log(m)
console.log(new Map([
['name','alex'],
['age',18]
]))
1.3.2什么时候使用Map:如果只是需要key->value的结构,或者需要字符串以外的值做键;只有模拟现实世界的实体时,才使用对象。
1.4Map的应用
const m=new Map([
p1,{
color:'red',
backgroundColor:'yellow',
fontSize:'40px'
},
p2,{
color:'green',
backgroundColor:'blue',
fontSize:'40px'
},
p3,{
color:'pin',
backgroundColor:'white',
fontSize:'40px'
},
]);
m.forEach((propObj,elem)=>{
for(const p in propObj){
elem.style[p]=propObj[p]
}
})
1.5for...in方法
1.5.1定义:for...in语句用于遍历数组或对象属性,也就是说,for...in循环中的代码每执行一次,就会对数组的索引(或对象的属性)进行一次操作。
1.5.2语法:
(1)variable:每次循环时,variable会被赋值为不同的属性名。
(2)object:可迭代的对象,即:可遍历的对象。
for (variable in object){
}
1.5.3实例
(1)遍历数组
const arr=['a','b','c','d']
for (const key in arr){
console.log('索引key:',key)
console.log("元素arr[key]:",arr[key])
}
(2)遍历对象
const obj={
name:'alex',
age:18,
sex:'male'
}
for (const key in obj){
console.log(key)
console.log(obj[key])
}
遍历对象时,key 表示属性名;遍历数组时,key表示索引。
1.5.4区分forEach和for...in
(1)forEach和for...in都可以遍历数组
(2)for...in可以遍历对象,forEach不可以
(3)for...in支持break和continue关键字,forEach不支持。以break关键字为例:
a)for...in方法:
const obj={
name:'alex',
age:18,
sex:'female'
}
for(const item in obj){
console.log(item)
if(item=='name'){
break;
}
}
b)forEach方法
const arr=['a','b','c','d']
arr.forEach(elem=>{
console.log(elem)
if(elem=='b'){
break
}
})
//打印结果报错
三、遍历器与for...of
1.Iterator的作用:遍历器(迭代器)
2.使用Iterator
const it=[1,2][Symbol.iterator]();
console.log(it.next());//{value:1,done:false}
console.log(it.next());//{value:2,done:false}
console.log(it.next());//{value:undefined,done:true}
//it:可遍历对象
//Symbol.iterator:可遍历对象的生成方法
3.什么是Iterator
Symbol.iterator(可遍历对象的生成方法) ->(可遍历对象)。
4.为什么需要Iterator遍历器
(1)遍历数组:for循环和forEach方法
(2)遍历对象:for in循环
Iterator遍历器是一个统一的遍历方法
5.for...of的用法
const arr=[1,2,3]
const it=arr[Symbol.iterator]()
let next=it.next();
while(!next.done){
console.log(next.value);
next=it.next();
console.log(next)
}
//for...of就是Iterator封装好之后的
for(const item of arr){
console.log(item)
}
//for...of循环只会遍历出那些done为false时,对应的value值
5.1:for...of 可以与break和continue一起使用
const arr=[1,2,3]
for (const item of arr){
if(item===2){
break;
//continue
}
}
5.2:在for...of中取得数组的索引
const arr[1,2,3]
console.log(arr.keys());
//keys()得到的是索引的可遍历对象,可以遍历出索引值
for(const key of arr.keys()){
console.log(key)
}
console.log(arr.values())
//values()得到的是值是可遍历对象,可以遍历出值
for(const value of arr.values()){
console.log(value)
}
//entries()得到的是索引+值组成的数组的可遍历对象
for(const key entrie arr.entries()){
console.log(entrie)
}
6.原生可遍历和非原生可遍历
6.1:什么是可遍历:
只要有Symbol.iterator方法,并且这个方法可以生成可遍历对象,就是可遍历的;只要可遍历,就可以使用for...of循环来统一遍历
6.2:原生可遍历的:数组、字符串、Set、Map、arguments、NodeList
//数组
for(const item of [1,2,3]){
console.log(item)
}
//字符串
for(const item of 'hi'){
console.log(item)
}
//Set
for(const item of new Set([1,2])){
console.log(item)
}
//Map
for (const item of new Map([
['name', 'alex'],
['age', 18]
])) {
console.log(item)
}
//arguments
for(const elem of document.querySelectorAll('p')){
console.log(elem);
elem.style.color='red'
}
//NodeList
6.3:非原生可遍历的:
一般的对象:
const person={sex:'male',age:18};
console.log(person[Symbol.iterator]())
//打印结果报错,因为一般的对象是没有Symbol.iterstor方法的
//没有Symbol.iterator方法,我们给他添加一个这个方法
person[Symbol.iterator]=()=>{
let inedx=0;
return{
next(){
index++;
if(index===1){
return{
value:person.age,
done:false
};
}else if(index===2){
return{
value:person.sex,
done:false
};
}else{
return{
done:true
}
}
}
}
}
//有 length 和索引属性的对象
const obj = {
'0': 'alex',
'1': 'male',
length: 2
};
obj[Symbol.iterator] = Array.prototype[Symbol.iterator];
obj[Symbol.iterator] = () => {
let index = 0;
return {
next() {
let value, done;
if (index < obj.length) {
value = obj[index];
done = false;
} else {
value = undefined;
done = true;
}
index++;
return {
value,
done
};
}
};
};
for (const item of obj) {
console.log(item);
}
四、ES6的新增方法
1.includes():
判断字符串中是否含有某些字符(返回的布尔值),或判断数组中是否含有某个成员
console.log('abc'.includes('a'))//true console.log('abc'.includes('ac'))//false //第二个参数:表示开始搜素的位置,默认是0 console.log('abc'.includes('a',0)) console.log([1,2,3].includes(2)); //基本遵循严格相等(===),但是对于NaN的判断与===不同,includes认为NaN===NaN console.log(NaN===NaN) //结果:false console.log([1,2,3,NaN].includes(NaN)) //结果:true
1.1应用
//https://www.imooc.com/course/list //https://www.imooc.com/course/list?c=fe&sort=pop&name=value let url='https://www.imooc.com/course/list'; const addURLParam=(url,name,value)=>{ url+=url.includes('?')?'&':'?'; url+=`${name}=${value}`; return url; }; url=addURLParam(url,'c','fe'); console.log(url); url=addURLParam(url,'sort','pop') console.log(url) //includes在数组中的应用:去重 const arr=[]; for (const item of [1,2,1]){ if(!arr.includes(item)){ arr.push(item); } } console.log(arr)
2.padStart()和padEnd():补全字符串长度
console.log('x'.padStart(5,'ab'))
//5:为补全之后的长度,结果为ababx
console.log('x'.padEnd(4,'ab'))
//结果:xaba
2.1注意事项
用来补全的字符串与原字符串长度之和超过了最大长度,截取超出位数的补全字符串,原字符不动。
console.log('xxx'.padStart(2,'ab'))
//结果为:xxx
用来补全的字符串与原字符串长度之和超过了最大长度,截取超出位数的补全字符串,原字符串不动。
console.log('abc'.padStart(10,'0123456789'))
//结果:0123465abc
如果省略第二个参数,默认用空格补全长度。
3.trimStart()【trimLeft()】和trimEnd()【trmiRight()】:
清除首或尾的空格,中间的空格不会清除。trim():清除首尾的空格。
4.Array,.from():
将其他数据类型转换成数组。
console.log(Array.from('arr'));
//结果:['a','r','r']
4.1:那些可以通过Array.from()转换成数组
(1)所有可遍历的:数组、字符串、Set、Map、NodeList、arguments
console.log(Array.from(new Set([1,2,1])))
//结果:[1,2]
console.log([...new Set([1,2,1])])
//结果:[1,2]
(2)拥有属性的任意对象
const obj={
'0':'a',
'1':'b',
length:1
};
console.log(Array.from(obj))
//结果:['a']
const obj={
'0':'a',
'1':'b',
length:2
};
console.log(Array.from(obj))
//结果:['a','b']
const obj={
'0':'a',
'1':'b',
name:'alex',
length:3
};
console.log(Array.from(obj))
//结果:['a','b',undefined]
4.2:第二个参数:作用类似于数组的Map方法,用来对买个元素进行处理,经处理后的值放入返回的数组。
console.log([1,2].map(value=>value*2))
//结果:[2,4]
console.log(Array.from('12',value=>value*2))
console.log(Array.from(''12').map(value=>value*2))
//结果:[2,4]
4.3:第三个参数:修改它的this指向
Array.from('12',value=>{
console.log(this);
},document)
//document为第三个参数,用来修改它的this指向,但在这并不能修改成功,因为用了箭头函数,箭头函数
//在声明的时候就确定好了this指向,要改变它的this指向用其他函数。
Array.from('12',function(){
console.log(this)
},doucment)
//this指向改为了document
5.find()
【找到满足的一个立即返回】和findindex()【找到满足条件的一个,立即返回其索引】
[1,5,10,15].find((value,index,arr)=>{ console.log(value,index,arr) return value>9 }) //结果:10 [1,5,10,15].findindex((value,index,arr)=>{ console.log(value,index,arr) return value>9 }) //结果:2
6.Object.assign(目标对象,源对象1,源对象2,...):
合并对象(可以合并多个对象)
const apple={ color:'red', shape:'球形', taste:'甜' }; const pen={ color:'black', shape:'圆柱形', use:'写字' } console.log(Object.assign(apple,pen)) //结果:{color:'black',shape:'圆柱形',taste:'甜',use:'写字'} console.log(Object.assign(apple,pen)===apple) //结果:true
6.1:注意事项
(1)基本数据类型作为源对象,与对象的展开类似,先转换成对象,再合并。
(2)Object.assign()直接合并到了第一个参数中,返回的就是合并后的对象,因此目标对象一般用空对象。
(3)同名属性的替换:后面的直接覆盖前面的。
6.3应用
//合并默认参数和用户参数
const logUser=userOptions=>{
const DEFAULTS={
username:'ZhangSan',
age:18,
sex:'male'
};
const options=Object.assign({},DEFAULTS,userOptions);
console.log(options)
}
logUser();
7.Object.keys()、Object.values()和Object.entries()
const person={
name:'alex',
age:18,
sex:'male'
};
console.log(Object.keys(person));
//['name','age','sex']
console.log(Object.values(person));
//['alex',18,'male']
console.log(Object.entries(person));
//[['name','alex'],['age',18],['sex','male']]
7.1与数组类似方法的区别:
(1)数组的keys()、values()、entries()等方法是实例方法,返回的都是iterator。
(2)对象的Object.keys()、Object.values()、Object.entries()等方法是构造函数方法,返回的是数组。
const person={
name:'alex',
age:18,
sex:'male'
}
for(const key of person ){
console.log(key)
}
//打印报错,因为person不是Iterator,可以如下这样做
for(const key of Object.keys(person)){
console.log(key)
}
(3)Object.keys()、Object.values()、Object.entries()等方法并不能保证顺序一定是你看到的样子,这一点和for in 是一样的。