以下文章来源于前端之神
ES6
1、let和const
这两个的出现,总感觉是为了开发的代码规范而出现的。我们要逐渐放弃var,在项目中多用let和const
与var的区别:
var有变量提升,有初始化提升,值可变
let有变量提升,没有初始化提升,值可变
const有变量提升,没有初始化提升,值不可变,但如果是定义对象,则属性可变
暂时性死区问题说明:其实let和const是有变量提升的,但是没有初始化提升:
varname=林三心
functionfn(){
console.log(name)
letname=sunshin_lin
}
fn()//Cannotaccessnamebeforeinitialization
块级作用域解决问题:
for(vari=0;i5;i++){
setTimeout(()={
console.log(i)
})
}//
for(leti=0;i5;i++){
setTimeout(()={
console.log(i)
})
}//
2、默认参数
开发中你曾遇到过这样的问题,如果参数不传进来,你就设置默认参数
functionfn(name,age){
varname=name
林三心
varage=age
18
console.log(name,age)
}
fn()//林三心18
但是这么写确实不优雅,可以使用ES6的默认参数
functionfn(name=林三心,age=18){
console.log(name,age)
}
fn()//林三心18
fn(sunshine,22)//sunshine22
3、扩展运算符
曾经的我,想要拼接多个数组,我只能这么做
constarr1=[1,2,4]
constarr2=[4,5,7]
constarr3=[7,8,9]
constarr=arr1.concat(arr2).concat(arr3)
[
1,2,4,4,5,
7,7,8,9
]
现在的我,可以更优雅地进行拼接
constarr1=[1,2,4]
constarr2=[4,5,7]
constarr3=[7,8,9]
constarr=[...arr1,...arr2,...arr3]
[
1,2,4,4,5,
7,7,8,9
]
4、剩余参数
大家可能遇到过这种问题,一个函数,传入参数的个数是不确定的,这就可以用ES6的剩余参数
functionfn(name,...params){
console.log(name)
console.log(params)
}
fn(林三心,1,2)//林三心[1,2]
fn(林三心,1,2,3,4,5)//林三心[1,2,3,4,5]
5、模板字符串
以前的我,拼接字符串只能这么做
constname=林三心
constage=22
console.log(name+今年+age+岁啦)//林三心今年22岁啦
现在我可以这么做,会更优雅
constname=林三心
constage=22
console.log(`${name}今年${age}岁啦`)//林三心今年22岁啦
6、Object.keys
可以用来获取对象的key的集合,进而可以获得对应key的value
constobj={
name:林三心,
age:22,
gender:男
}
constkeys=Object.keys(obj)
console.log(keys)//[name,age,gender]
7、箭头函数
以前我们使用普通函数
functionfn(){}
constfn=function(){}
ES6新加了箭头函数
constfn=()={}
//如果只有一个参数,可以省略括号
constfn=name={}
//如果函数体里只有一句return
constfn=name={
return2*name
}
//可简写为
constfn=name=2*name
//如果返回的是对象
constfn=name=({name:name})
普通函数和箭头函数的区别:
1、箭头函数不可作为构造函数,不能使用new
2、箭头函数没有自己的this
3、箭头函数没有arguments对象
4、箭头函数没有原型对象
8、Array.forEach
ES6新加的数组遍历方法
consteachArr=[1,2,3,4,5]
//三个参数:遍历项索引数组本身
//配合箭头函数
eachArr.forEach((item,index,arr)={
console.log(item,index,arr)
})
10[1,2,3,4,5]
21[1,2,3,4,5]
32[1,2,3,4,5]
43[1,2,3,4,5]
54[1,2,3,4,5]
9、Array.map
常用于返回一个处理过后的新数组
constmapArr=[1,2,3,4,5]
//三个参数:遍历项索引数组本身
//配合箭头函数,对每一个元素进行翻倍
constmapArr2=mapArr.map((num,index,arr)=2*num)
console.log(mapArr2)
[2,4,6,8,10]
10、Array.filter
顾名思义,用来过滤的方法
constfilterArr=[1,2,3,4,5]
//三个参数:遍历项索引数组本身
//配合箭头函数,返回大于3的集合
constfilterArr2=filterArr.filter((num,index,arr)=num3)
console.log(filterArr2)
[4,5]
11、Array.some
some,意思就是只有一个是真,那就返回真
constsomeArr=[false,true,false,true,false]
//三个参数:遍历项索引数组本身
//配合箭头函数,只要有一个为true,就返回true,一个都true都没有,就返回false
constsomeArr2=someArr.some((bol,index,arr)=bol)
console.log(someArr2)
true
12、Array.every
every跟some是相反的,some是只有一个就行,every是要所有为真才返回真
consteveryArr=[false,true,false,true,false]
//三个参数:遍历项索引数组本身
//配合箭头函数,需要所有为true,才返回true,否则返回false
consteveryArr2=everyArr.every((bol,index,arr)=bol)
console.log(everyArr2)
13、Array.reduce
第一个参数callback函数:pre为上次return的值,next为数组的本次遍历的项
第二个参数为初始值,也是第一个pre
举两个例子:
//计算1+2+3+4+5
constreduceArr=[1,2,3,4,5]
constsum=reduceArr.reduce((pre,next)={
returnpre+next
},0)
console.log(sum)//15
//统计元素出现个数
constnameArr=[林三心,sunshine_lin,林三心,林三心,科比]
consttotalObj=nameArr.reduce((pre,next)={
if(pre[next]){
pre[next]++
}else{
pre[next]=1
}
returnpre
},{})
console.log(totalObj)//{林三心:3,sunshine_lin:1,科比:1}
14、对象属性同名简写
以前同名属性需要这么写
constname=林三心
constage=22
constobj={
name:name,
age:age
}
console.log(obj)//{name:林三心,age:22}
ES6新增语法,只需这么写
constname=林三心
constage=22
//属性同名可简写
constobj={
name
age
}
console.log(obj)//{name:林三心,age:22}
15、Promise
Promise,中文名为承诺,承诺在哪呢?承诺在,一旦他的状态改变,就不会再改。这里就介绍基本使用,如果想要深入理解如何使用,请看我的另一篇文章看了就会,手写Promise原理,最通俗易懂的版本!!!
看看基本使用
成功状态
functionrequestData(){
//模拟请求
returnnewPromise((resolve,reject)={
setTimeout(()={
resolve(林三心)
},)
})
}
requestData().then(res={
console.log(res)//一秒钟后输出林三心
},err={
console.log(err)
})
失败状态
functionrequestData(){
//模拟请求
returnnewPromise((resolve,reject)={
setTimeout(()={
reject(错误啦)
},)
})
}
requestData().then(res={
console.log(res)
},err={
console.log(err)//一秒钟后输出错误啦
})
all方法
接收一个Promise数组,数组中如有非Promise项,则此项当做成功
如果所有Promise都成功,则返回成功结果数组
如果有一个Promise失败,则返回这个失败结果
//如果全都为成功
functionfn(time){
returnnewPromise((resolve,reject)={
console.log(88)
setTimeout(()={
resolve(`${time}毫秒后我成功啦!!!`)
},time)
})
}
Promise.all([fn(),fn(),fn()]).then(res={
//3秒后输出[毫秒后我成功啦!!!,毫秒后我成功啦!!!,毫秒后我成功啦!!!]
console.log(res)
},err={
console.log(err)
})
//如果有一个失败
functionfn(time,isResolve){
returnnewPromise((resolve,reject)={
setTimeout(()={
isResolve?resolve(`${time}毫秒后我成功啦!!!`):reject(`${time}毫秒后我失败啦!!!`)
},time)
})
}
Promise.all([fn(,true),fn(),fn(,true)]).then(res={
console.log(res)
},err={
console.log(err)//3秒后输出毫秒后我失败啦!!!
})
race方法
接收一个Promise数组,数组中如有非Promise项,则此项当做成功
哪个Promise最快得到结果,就返回那个结果,无论成功失败
functionfn(time,isResolve){
returnnewPromise((resolve,reject)={
setTimeout(()={
isResolve?resolve(`${time}毫秒后我成功啦!!!`):reject(`${time}毫秒后我失败啦!!!`)
},time)
})
}
Promise.race([fn(,true),fn(),fn()]).then(res={
console.log(res)
},err={
console.log(err)//1秒后输出
})
16、class
以前咱们使用构造函数生成对象,这么做
functionPerson(name){
this.name=name
}
Person.prototype.sayName=function(){
console.log(this.name)
}
constkobe=newPerson(科比)
kobe.sayName()//科比
而有了ES6的class可以这么做
classPerson{
constructor(name){
//构造器
this.name=name
}
sayName(){
console.log(this.name)
}
}
constkobe=newPerson(科比)
kobe.sayName()//科比
值得一提的是,class本质也是function,class是function的语法糖
classPerson{}
console.log(typeofPerson)//function
除了以上,还需要知道class的以下知识点
静态属性和静态方法,使用static定义的属性和方法只能class自己用,实例用不了
classPerson{
constructor(name){
this.name=name
}
staticage=22
staticfn(){
console.log(哈哈)
}
}
console.log(Person.age)//22
Person.fn()//哈哈
constsunshine_lin=newPerson(林三心)
console.log(sunshine_lin.age)//undefined
sunshine_lin.fn()//fnisnotafunction
extend继承
classAnimal{
constructor(name,age){
this.name=name
this.age=age
}
}
classCatextendsAnimal{
say(){
console.log(this.name,this.age)
}
}
constcat=newCat(ketty,5)//继承了Animal的构造器
cat.say()//ketty5
17、解构赋值
以前想提取对象里的属性需要这么做
constobj={
name:林三心,
age:22,
gender:男
}
constname=obj.name
constage=obj.age
constgender=obj.gender
console.log(name,age,gender)//林三心22男
ES6新增了解构赋值的语法
constobj={
name:林三心,
age:22,
gender:男,
doing:{
morning:摸鱼,
afternoon:摸鱼,
evening:sleep
}
}
const{name,age,gender}=obj
console.log(name,age,gender)//林三心22男
//解构重名
const{name:myname}=obj
console.log(myname)//林三心
//嵌套解构
const{doing:{evening}}=obj
console.log(evening)//sleep
也可以进行数组的解构
constarr=[1,2,3]
const[a,b,c]=arr
console.log(a,b,c)//
//默认赋值
const[a,b,c,d=5]=arr
console.log(a,b,c,d)//5
//乱序解构
const{1:a,0:b,2:c}=arr
console.log(a,b,c)//
18、find和findIndex
find:找到返回被找元素,找不到返回undefined
findIndex:找到返回被找元素索引,找不到返回-1
constfindArr=[
{name:科比,no:24},
{name:罗斯,no:1},
{name:利拉德,no:0}
]
constkobe=findArr.find(({name})=name===科比)
constkobeIndex=findArr.findIndex(({name})=name===科比)
console.log(kobe)//{name:科比,no:24}
console.log(kobeIndex)//0
19、forof和forin
forin:遍历方法,可遍历对象和数组
forof:遍历方法,只能遍历数组,不能遍历对象先看forin:
constobj={name:林三心,age:22,gender:男}
constarr=[1,2,3,4,5]
for(letkeyinobj){
console.log(key)
}
name
age
gender
for(letindexinarr){
console.log(index)
}
再看forof:
for(letitemofarr){
console.log(item)
}
45
20、Set和Map
Set先说说Set的基本用法
//可不传数组
constset1=newSet()
set1.add(1)
set1.add(2)
console.log(set1)//Set(2){1,2}
//也可传数组
constset2=newSet([1,2,3])
//增加元素使用add
set2.add(4)
set2.add(林三心)
console.log(set2)//Set(5){1,2,3,4,林三心}
//是否含有某个元素使用has
console.log(set2.has(2))//true
//查看长度使用size
console.log(set2.size)//5
//删除元素使用delete
set2.delete(2)
console.log(set2)//Set(4){1,3,4,林三心}
再说说Set的不重复性
//增加一个已有元素,则增加无效,会被自动去重
constset1=newSet([1])
set1.add(1)
console.log(set1)//Set(1){1}
//传入的数组中有重复项,会自动去重
constset2=newSet([1,2,林三心,3,3,林三心])
console.log(set2)//Set(4){1,2,林三心,3}
Set的不重复性中,要注意引用数据类型和NaN
//两个对象都是不用的指针,所以没法去重
constset1=newSet([1,{name:林三心},2,{name:林三心}])
console.log(set1)//Set(4){1,{name:林三心},2,{name:林三心}}
//如果是两个对象是同一指针,则能去重
constobj={name:林三心}
constset2=newSet([1,obj,2,obj])
console.log(set2)//Set(3){1,{name:林三心},2}
咱们都知道NaN!==NaN,NaN是自身不等于自身的,但是在Set中他还是会被去重
constset=newSet([1,NaN,1,NaN])
console.log(set)//Set(2){1,NaN}
利用Set的不重复性,可以实现数组去重
constarr=[1,2,3,4,4,5,5,66,9,1]
//Set可利用扩展运算符转为数组哦
constquchongArr=[...newSet(arr)]
console.log(quchongArr)//[1,2,3,4,5,66,9]
MapMap对比object最大的好处就是,key不受类型限制
//定义map
constmap1=newMap()
//新增键值对使用set(key,value)
map1.set(true,1)
map1.set(1,2)
map1.set(哈哈,嘻嘻嘻)
console.log(map1)//Map(3){true=1,1=2,哈哈=嘻嘻嘻}
//判断map是否含有某个key使用has(key)
console.log(map1.has(哈哈))//true
//获取map中某个key对应的value使用get(key)
console.log(map1.get(true))//2
//删除map中某个键值对使用delete(key)
map1.delete(哈哈)
console.log(map1)//Map(2){true=1,1=2}
//定义map,也可传入键值对数组集合
constmap2=newMap([[true,1],[1,2],[哈哈,嘻嘻嘻]])
console.log(map2)//Map(3){true=1,1=2,哈哈=嘻嘻嘻}
ES7
21、includes
传入元素,如果数组中能找到此元素,则返回true,否则返回false
constincludeArr=[1,2,3,林三心,科比]
constisKobe=includeArr.includes(科比)
console.log(isKobe)//true
跟indexOf很像,但还是有区别的
constarr=[1,2,NaN]
console.log(arr.indexOf(NaN))//-1indexOf找不到NaN
console.log(arr.includes(NaN))//trueincludes能找到NaN
22、求幂运算符
以前求幂,我们需要这么写
constnum=Math.pow(3,2)//9
ES7提供了求幂运算符:**
constnum=3**2//9
ES8
23、Object.values
可以用来获取对象的value的集合
constobj={
name:林三心,
age:22,
gender:男
}
constvalues=Object.values(obj)
console.log(values)//[林三心,22,男]
24、Object.entries
可以用来获取对象的键值对集合
constobj={
name:林三心,
age:22,
gender:男
}
constentries=Object.entries(obj)
console.log(entries)
//[[name,林三心],[age,22],[gender,男]]
25、async/await
这个是很常用的语法了,我的理解就是:以同步方式执行异步操作
我们平时可能会遇到这种场景,接口一,请求到数据一,而数据一被当做请求二的参数去请求数据二,我们会用Promise这么做
functionfn(){
//模拟第一次请求
returnnewPromise((resolve,reject)={
setTimeout(()={
resolve(5)
},)
}).then(res={
//模拟第二次请求
newPromise((resolve,reject)={
setTimeout(()={
//拿第一次请求的数据去乘10,当做第二次请求的数据
resolve(res*10)
},)
}).then(sres={
console.log(sres)
})
})
}
fn()//1+2=33秒后输出50
这样的嵌套是不美观的,如果有很多个接口,那就会嵌套很多层,此时我们可以使用async/await来以同步方式执行异步,注意以下几点:
await只能在async函数里使用
await后面最好接Promise,如果后面接的是普通函数则会直接执行
async函数返回的是一个Promise
functionfn1(){
returnnewPromise((resolve,reject)={
setTimeout(()={
resolve(5)
},)
})
}
functionfn2(data){
returnnewPromise((resolve,reject)={
setTimeout(()={
resolve(data*10)
},)
})
}
asyncfunctionreq(){
//同步方式执行异步,像排队一样
constdata1=awaitfn1()//等待1秒后返回数据再往下执行
constdata2=awaitfn2(data1)//拿data1去请求2秒后,往下走
console.log(data2)//总共3秒后输出50
}
req()
ES9
26、forawaitof
我们来看以下场景哈
functionfn(time){
returnnewPromise((resolve,reject)={
setTimeout(()={
resolve(`${time}毫秒后我成功啦!!!`)
},time)
})
}
fn().then(res=console.log(res))
fn().then(res=console.log(res))
fn().then(res=console.log(res))
结果是
毫秒后我成功啦!!!
毫秒后我成功啦!!!
毫秒后我成功啦!!!
但是我想要这个结果
毫秒后我成功啦!!!
毫秒后我成功啦!!!
毫秒后我成功啦!!!
第一时间我们肯定想到的是async/await
functionfn(time){
returnnewPromise((resolve,reject)={
setTimeout(()={
resolve(`${time}毫秒后我成功啦!!!`)
},time)
})
}
asyncfunctionasyncFn(){
//排队
constdata1=awaitfn()
console.log(data1)//3秒后毫秒后我成功啦!!!
constdata2=awaitfn()
console.log(data2)//再过1秒毫秒后我成功啦!!!
constdata3=awaitfn()
console.log(data3)//再过2秒毫秒后我成功啦!!!
}
但是上面代码也是有缺点的,如果有几十个,那不是得写几十个await,有没有一种方法可以通过循环来输出呢?
functionfn(time){
returnnewPromise((resolve,reject)={
setTimeout(()={
resolve(`${time}毫秒后我成功啦!!!`)
},time)
})
}
asyncfunctionasyncFn(){
constarr=[fn(),fn(),fn(),fn(),fn()]
forawait(letxofarr){
console.log(x)
}
}
asyncFn()
毫秒后我成功啦!!!
毫秒后我成功啦!!!
毫秒后我成功啦!!!
毫秒后我成功啦!!!
毫秒后我成功啦!!!
27、Promise.finally
新增的Promise方法,无论失败或者成功状态,都会执行这个函数
//cheng
newPromise((resolve,reject)={
resolve(成功喽)
}).then(
res={console.log(res)},
err={console.log(err)}
).finally(()={console.log(我是finally)})
newPromise((resolve,reject)={
reject(失败喽)
}).then(
res={console.log(res)},
err={console.log(err)}
).finally(()={console.log(我是finally)})
ES10
28、Array.flat
有一个二维数组,我想让他变成一维数组:
constarr=[1,2,3,[4,5,6]]
console.log(arr.flat())//[1,2,3,4,5,6]
还可以传参数,参数为降维的次数
constarr=[1,2,3,[4,5,6,[7,8,9]]]
console.log(arr.flat(2))
[
1,2,3,4,5,
6,7,8,9
]
如果传的是一个无限大的数字,那么就实现了多维数组(无论几维)降为一维数组
constarr=[1,2,3,[4,5,6,[7,8,9,[10,11,12]]]]
console.log(arr.flat(Infinity))
[
1,2,3,4,5,
6,7,8,9,10,
11,12
]
29、Array.flatMap
现在给你一个需求
letarr=["科比詹姆斯安东尼","利拉德罗斯麦科勒姆"];
将上面数组转为
[科比,詹姆斯,安东尼,利拉德,罗斯,麦科勒姆]
第一时间想到map+flat
console.log(arr.map(x=x.split("")).flat());
//[科比,詹姆斯,安东尼,利拉德,罗斯,麦科勒姆]
flatMap就是flat+map,一个方法顶两个
console.log(arr.flatMap(x=x.split("")));
//[科比,詹姆斯,安东尼,利拉德,罗斯,麦科勒姆]
30、BigInt
BigInt是ES10新加的一种JavaScript数据类型,用来表示表示大于2^53-1的整数,2^53-1是ES10之前,JavaScript所能表示最大的数字