• ES7-ES13有何新特性?


    目录

    ES7

    ES8

    ES9

    ES10

    ES11

    ES12

    ES13


    hello,大家好呀!之前发布的两篇关于ES6新特性的文章学习完了吗?今天来给大家介绍ES6之后,截止到2022年的ES13每个时期新增的一些新特性!快来一起学习吧!

    ES7

    Array.prototype.includes

    Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值。在原本的判断中我们一般会使用indexOf来进行判断,但是返回的是数字,比较明了,因此使用includes来进行判断能够更加地简便。

    1. var arr=['ES6','ES7','ES8','ES9']
    2. console.log(arr.includes('ES6'))//true
    3. console.log(arr.includes('ES12'))//false

    指数操作符

    在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同。

    1. let x=2;
    2. console.log(x**10);//1024
    3. console.log(Math.pow(x,10));//1024

    ES8

    async 和 await

    async 和 await 两种语法结合可以让异步代码像同步代码一样。在前面我们介绍ES6时说到了一些可以解决异步问题的方法,比如生成器以及Promise。而async一级await同样是用来解决异步问题的方法。

    async函数返回的值是一个promise对象,该对象的结果由async函数执行的返回值决定。此部分与promise中的then方法相同。有兴趣的可以看我上一篇文章!在此就不过多赘述。

    1. async function fn(){
    2. return new Promise((resolve,reject)=>{
    3. reject('失败的错误');
    4. })
    5. }
    6. const result=fn();
    7. console.log(result);//[[PromiseState]]: "rejected" [[PromiseResult]]: "失败的错误"

    await表达式,await 必须写在 async 函数中,右侧的表达式一般为 promise 对象。await 返回的是 promise 成功的值,await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理。

    1. // 创建一个promise对象
    2. const p=new Promise((resolve,reject)=>{
    3. // 成功时
    4. // resolve("用户数据!");
    5. // 失败时
    6. reject("失败啦!")
    7. })
    8. async function main(){
    9. try{
    10. let result=await p;
    11. console.log(result);
    12. }catch(e){
    13. console.log(e);
    14. }
    15. }
    16. main();

    使用async以及await来实现发送Ajax请求,(接口可能有点问题,但是编写方式应该是没有问题的)

    1. // 发送AJAX请求,返回的结果是Promise对象
    2. function send(url){
    3. return new Promise((resolve,reject)=>{
    4. let xhr=new XMLHttpRequest();
    5. xhr.open('GET',url);
    6. xhr.send();
    7. xhr.onreadystatechange=function(){
    8. if(xhr.readyState==4){
    9. if(xhr.status>=200 && xhr.status<300){
    10. resolve(xhr.response);
    11. }else{
    12. reject(xhr.status);
    13. }
    14. }
    15. }
    16. })
    17. }
    18. async function main(){
    19. let result=await send("https://api.apiopen.top/getJoke");
    20. console.log(result);
    21. }
    22. main();

    对象方法扩展

    Object.values()方法返回一个给定对象的所有可枚举属性值的数组。

    Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数。对象的一对键和值作为一个数组,第一个元素为健第二个元素为值。

    Object.getOwnPropertyDescriptors()该方法返回指定对象所有自身属性的描述对象。返回的是一个对象,对象名为健名,对象内部有四个属性,value为值,configurable是否可以删除,enumerable是否可以枚举以及writable是否可以写。

    1. const plan={
    2. name:'N-A',
    3. study:['ES6','ES7','ES8','ES9']
    4. }
    5. // 获取对象的所有健
    6. console.log(Object.keys(plan));//['name', 'study']
    7. // 获取对象的所有值
    8. console.log(Object.values(plan));//['N-A', Array(4)]
    9. //对象的健和值作为一个数组
    10. console.log(Object.entries(plan));//[Array(2), Array(2)]
    11. //对象属性的描述对象
    12. console.log(Object.getOwnPropertyDescriptors(plan));

    ES9

    扩展运算符和rest参数

    之前我们已经有介绍过它们了,为啥这次有介绍呢,因此在之前他们只是针对数组进行的操作,而ES9让它们可以为对象所服务了。

    1. // rest参数
    2. function connect({name,age,...args}){
    3. console.log(name);//'N-A'
    4. console.log(age);//5
    5. console.log(args)//{sex: '男', study: 'ES9'}
    6. }
    7. connect({
    8. name:'N-A',
    9. age:5,
    10. sex:'男',
    11. study:'ES9'
    12. });
    13. //扩展运算符
    14. const studyOne={
    15. one:'ES6'
    16. }
    17. const studyTwo={
    18. two:'ES7'
    19. }
    20. const studyThree={
    21. three:'ES8'
    22. }
    23. const study={...studyOne,...studyTwo,...studyThree};
    24. console.log(study);//{one: 'ES6', two: 'ES7', three: 'ES8'}

    正则扩展

    ES9 允许命名捕获组使用符号『?』,这样获取捕获结果可读性更强。提取也会更加地方便以及以后的维护也会更加地好。

    1. // 声明一个字符串
    2. let str='哔哩哔哩';
    3. // 传统的提取url与子标签中的文本
    4. const reg=/(.*)<\/a>/;

    同时,ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。

    1. // 若想要提取91011这串数字
    2. let str='今天学习ES9,你知道ES91011的新特性吗?';
    3. // 正向断言
    4. const reg=/\d+(?=的)/;
    5. const result=reg.exec(str);
    6. // 反向断言
    7. const reg2=/(?<=道ES)\d+/;
    8. const result2=reg2.exec(str);

    正则表达式中点.匹配除回车外的任何单字符,标记『s』改变这种行为,允许行终止符出现。使用点就可以直接替换成之前编写比较复杂的换行或者空格的模式,让其更加的容易编写。

    1. let str = `
    2. 上映日期: 1994-09-10

  • 上映日期: 1994-07-06

  • `;
  • //声明正则
  • const reg = /
  • .*?(.*?)<\/a>.*?

    (.*?)<\/p>/gs;

  • ES10

    对象扩展方法

    Object.fromEntries()该方法用来创建一个对象,该方法的参数可以接收一个二维数组或者一个Map。它是ES8中介绍的Object.entries的逆运算。

    1. // 二维数组
    2. const result=Object.fromEntries([
    3. ['name','N-A'],
    4. ['study','ES10']
    5. ]);
    6. console.log(result);//{name: 'N-A', study: 'ES10'}
    7. // Map
    8. const m=new Map();
    9. m.set('name','N-A');
    10. const result2=Object.fromEntries(m);
    11. console.log(result2);//{name: 'N-A'}

    字符串扩展方法

    trimStart和 trimEnd,我们知道trim()方法用来清除字符串中两侧的空白,而ES10提供的trimStart用于指定清除字符串左侧的空白,trimEnd用于指定清除字符串右侧的空白。

    数组扩展方法

    Array.prototype.flat与 flatMap,flat函数可以将多维的数组转为低纬度的数组,可以传一个参数,代表深度。flatMap方法相当于是Map以及flat方法的结合,当Map方法返回的数值较为复杂时,比如多维的数组,则可以直接使用flatMap来进行转换。

    1. // flat
    2. const arr=[1,2,3,4,[5,6]];
    3. const arr2=[1,2,3,[4,5,[7,8]]];
    4. console.log(arr.flat());//[1, 2, 3, 4, 5, 6]
    5. console.log(arr2.flat());//[1, 2, 3, 4, 5, Array(2)]
    6. console.log(arr2.flat(2));//[1, 2, 3, 4, 5, 7, 8]
    7. //flatMap
    8. const arr3=[1,2,3,4];
    9. const result=arr3.flatMap(item=>[item*10]);
    10. console.log(result);//[10, 20, 30, 40]

    Symbol的扩展

    Symbol.prototype.description其作用可以获取创建Symbol时相应的具体的值。

    1. // 创建 Symbol
    2. let s=Symbol('N-A');
    3. console.log(s.description);//N-A

    ES11

    类的私有属性

    在类中使用#号加变量名的方式声明变量,只能在类的内部被访问到,在类外面无法被访问到。

    1. class Person{
    2. name;
    3. #age;
    4. constructor(name,age){
    5. this.name=name;
    6. this.#age=age;
    7. }
    8. intro(){
    9. console.log(this.name);
    10. console.log(this.#age);
    11. }
    12. }
    13. // 实例化
    14. const person=new Person('N-A',5);
    15. console.log(person.name);//N-A
    16. console.log(person.#age);//报错
    17. person.intro();//N-A 5

    Promise.allSettled

    在ES11中为Promise新增了allSettled的方法,与all方法相似,都是用于对多个异步操作进行处理。不同点在与allSettled不管异步的操作是否成功,都会返回成功的状态。成功以及失败的返回的数据即为它对应的值,用数组进行存储。而all需要全部都成功时才会是成功的状态。同样,成功的所有数据则为all的数据,用数组进行存储。若是失败的状态值为undefined。

    1. const p1=new Promise((resolve,reject)=>{
    2. setTimeout(()=>{
    3. resolve('商品数据-1');
    4. },1000)
    5. });
    6. const p2=new Promise((resolve,reject)=>{
    7. setTimeout(()=>{
    8. resolve('商品数据-2');
    9. // reject('数据失败')
    10. },1000)
    11. });
    12. const result=Promise.allSettled([p1,p2]);
    13. const result2=Promise.all([p1,p2]);
    14. console.log(result);
    15. console.log(result2);

    String.prototype.matchAll

    该方法对于数据的批量提取很有帮助,还是我们上面列举到的例子,提取标签中电影的名字以及上映的时间。使用matchAll进行提取如下:

    1. let str = `
      • 上映日期: 1994-09-10

      • 上映日期: 1994-07-06

      • `;
      • //声明正则
      • const reg = /
      • .*?(.*?)<\/a>.*?

        (.*?)<\/p>/gs;

      可选链操作符

      它的形式为:?.使用的场景为当我们在使用对象里面的参数时,对象的层级比较深,我们需要做一层层的判断,因此比较麻烦。使用可选链操作可以省去很多麻烦,不需要再做层级的判断。

      1. function main(config){
      2. // 使用原先的方法
      3. const dbHost=config && config.db && config.db.host;
      4. // 若直接赋值,用户不传入参数时会报错
      5. const dbHost2=config.db.host;
      6. // 使用可选链式操作符,会先判断config值是否有,若有在去读取后面的db,以此类推。
      7. //若用户没有传入参数,也不会报错,会返回undefined。
      8. const dbHost3=config?.db?.host;
      9. }
      10. main({
      11. db:{
      12. host:'192.168.1.100',
      13. username:'root'
      14. },
      15. cache:{
      16. host:'192.168.1.200',
      17. username:'admin'
      18. }
      19. })
      20. // 没传参
      21. main()

      动态导入import

      在前面的ES6中我们介绍了模块化的静态导入,但是如果导入太多的文件,在某些时刻又不需要使用到就会很影响性能。因此我们可以使用ES11中提供的动态导入方法。import返回的结果是一个promise对象,而这个对象的值即为我们暴露出来的对象。

      1. //app.js
      2. const btn=document.getElementById('btn');
      3. btn.onclick=function(){
      4. import('./hello.js').then(module=>{
      5. module.hello();
      6. });
      7. }
      8. //hello.js
      9. export function(){
      10. alter('hello')
      11. }
      12. //index.html
      13. <button id="btn">点击button>
      14. <script src="./js/app.js" type="module">script>

      BigInt

      BigInt为ES11新增的一个数据类型,大整型,主要是用于处理大数据的运算。它的声明方式为普通的数字后面加上字母n。它还有一个方法BigInt()传入一个整数,可以让该整数的类型变成大整形,它不能够传入浮点数。除此之外,一个大整型的数据不能直接与一个普通的整型数据进行加减运算,需要都是大整型才可以。

      1. let n=234n;
      2. console.log(n,typeof(n));//234n 'bigint'
      3. let m=123;
      4. console.log(BigInt(m));//123n
      5. // 大数值运算
      6. let max=Number.MAX_SAFE_INTEGER;
      7. console.log(BigInt(max));
      8. console.log(BigInt(max)+BigInt(12));

      globalThis

      在ES11中引入了绝对全局对象globalThis,该对象无论执行环境是什么始终指向全局对象。

      ES12

      新增逻辑操作符

      1. let a=true;
      2. let b=false;
      3. // 相当于a=a&&b
      4. console.log(a&&=b);//false
      5. // 相当于a=a||b
      6. console.log(a||=b);//false
      7. let obj={
      8. apply:0
      9. }
      10. // 相当于obj.apply=obj.apply??'哈哈哈'
      11. console.log(obj.apply??='哈哈哈')//0

      数字分隔符

      这个新特性是为了方便程序员看代码出现的,如果数字比较大,那么看起来就不是那么一目了然。分隔符不仅可以分割十进制,也可以分割二进制或者十六进制的数据。

      1. let num=123_456_789
      2. let num1=123456789
      3. console.log(num===num1)//true
      4. let num2=0b0010_1010
      5. let num3=0o12_34_56
      6. let num4=0xa1_b2_c3

      replaceAll

      所有匹配都会被替代项替换,模式可以是字符串或者是正则表达式,而替换项可以是字符串或针对每次匹配执行的函数,并返回一个全新的字符串。

      1. let str='hello I am N-A,I am study the ES11。hello I am N-A,I am study the ES12。'
      2. //若想要将里面的所有N-A替换成@,则可以使用以下的几种方式
      3. //传统的replace只能够替换第一个
      4. console.log(str.replace('N-A',"#"))
      5. // 使用正则来进行全局替换
      6. console.log(str.replace(/N-A/g,"#"))
      7. // 使用replaceAll来进行替换
      8. console.log(str.replaceAll('N-A',"#"))

      Promise.any

      该方法接受多个异步请求,若其中有一个请求返回的状态是成功的,则它的状态为成功,对应的值为最先完成成功的请求成功的值。若所有的请求的状态都是失败的,状态则为失败,它会执行.catch方法。

      1. let ajax1=function(){
      2. return new Promise((resolve,reject)=>{
      3. resolve("1111")
      4. })
      5. }
      6. let ajax2=function(){
      7. return new Promise((resolve,reject)=>{
      8. resolve("2222")
      9. })
      10. }
      11. let ajax3=function(){
      12. return new Promise((resolve,reject)=>{
      13. resolve("3333")
      14. })
      15. }
      16. Promise.any([ajax1(),ajax2(),ajax3()]).then(res=>{
      17. console.log(res)//1111
      18. }).catch(err=>{
      19. console.error(err);
      20. })

      它与Promise.race()方法有点相似,但是不同点在于它不会因为某个Promise变成rejected状态而结束,它会等到所有参数Promise变成rejected状态才会结束。

      FinalizationRegistry

      清理器注册表功能FinalizationRegistry,用来指定目标对象被垃圾回收机制清除以后,所要执行的回调函数。一般比较少使用。

      WeakRef

      在一般情况下,对象的引用是强引用,这意味着只要持有对象的引用,它就不会被垃圾回收。只有当该对象没有任何的强引用时,垃圾回收才会销毁对象并且收回对象所占的内存空间。

      weakRef允许你保留对另一个对象的弱引用,而不会阻止被弱引用对象被垃圾回收。

      1. // obj为强引用
      2. let obj={
      3. name:'N-K'
      4. }
      5. //wobj为弱引用
      6. let wobj=new WeakRef(obj)
      7. // //obj赋为null之前
      8. console.log(wobj.deref())//{name: 'N-K'}
      9. // 当obj赋值为null时,wobj中的对象会被垃圾回收机制回收无法访问到
      10. obj = null
      11. //wobj中的对象会被垃圾回收机制回收无法访问到,从而可以防止内存泄漏
      12. console.log(wobj.deref())//undefined

      ES13

      类新增特性

      原本我们在类中创建一个构造器,但是并在里面声明一些属性传入参数时进行赋值,但是当有一些属性原本有自己的值并不需要进行传参时赋值时,我们可以直接将这些属性编写在constructor方法的外部即可。

      1. class Person{
      2. state={
      3. a:1,
      4. b:2
      5. }
      6. c=3;
      7. d=4;
      8. constructor(name,age){
      9. this.name=name
      10. this.age=age
      11. }
      12. }
      13. let obj=new Person('N-A',5)
      14. console.log(obj)//{state: {…}, c: 3, d: 4, name: 'N-A', age: 5}

      同时ES13允许在类中通过static关键字定义一系列静态代码块,这些代码块只会在类被创建的时候执行一次。

      1. class Person{
      2. static obj=new Map()
      3. static{
      4. this.obj.set('name','N-A')
      5. this.obj.set('study','ES13')
      6. }
      7. static{
      8. console.log(this.obj)
      9. }
      10. }
      11. //{'name' => 'N-A', 'study' => 'ES13'}

      还增加了in关键字用于判断某个属性是否为某个对象中的私有属性。

      最外层的await

      在之前使用await时都需要写在函数的内部并且需要配合async进行使用。而在ES13中await可以支持写在最外层中。而如果你想要在顶层使用await,则需要在modules中。

      顶层的await主要是用于模块化开发。比如我们在一个文件中声明一个对象并向外进行暴露,但是对象中的值需要进行异步的取到。这时候就可以使用顶层的await,它可以确保在数据放回来的时候模块再向外部暴露。可以实现导出的时候是异步导出,动态导入时直接await即可,不需要在async函数内部了。

      1. //index.js
      2. function ajax(){
      3. return new Promise((resolve)=>{
      4. setTimeout(()=>{
      5. resolve("用户数据")
      6. },2000)
      7. })
      8. }
      9. let data=await ajax()
      10. export default{
      11. name:'N-A',
      12. // 对象的省略方式
      13. data
      14. }
      1. html>
      2. <html lang="en">
      3. <head>
      4. <meta charset="UTF-8">
      5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
      6. <title>Documenttitle>
      7. head>
      8. <style>
      9. style>
      10. <body>
      11. <script type="module">
      12. console.log("开始")
      13. // 使用动态的导入避免阻塞上面代码的运行
      14. let module = await import('./index.js')
      15. console.log(module)
      16. script>
      17. body>
      18. html>

      at函数

      使用at函数可以取出数组或者字符串中对应的第几个元素。

      1. let arr=['ES6','ES7','ES8','ES9','ES10']
      2. // 数组第一个元素
      3. console.log(arr.at(0))//ES6
      4. // 数组最后一个元素
      5. console.log(arr.at(-1))//ES10
      6. let str='whekruuwkwo'
      7. console.log(str.at(0))//w
      8. console.log(str.at(-2))//w

      正则匹配的开始和结束索引

      1. let str='今天是2023-11-21'
      2. let reg=/(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/d
      3. let res=reg.exec(str)
      4. console.log(res)

      findLast和findLastIndex

      1. let arr=[11,12,13,14,15]
      2. let res=arr.find(value=>value>13)//14
      3. let res=arr.findIndex(value=>value>13)//3
      4. let res=arr.findLast(value=>value>13)//15
      5. let res=arr.findLastIndex(value=>value>13)//4

      Error对象的Cause属性

      Error对象多了一个cause属性来指明错误出现的原因,这个属性可以帮助我们为错误添加更多的上下文信息,从而帮助更好地对错误进行定位。

      1. function getData(){
      2. try{
      3. console.log(aaa)
      4. }catch{
      5. throw new Error('参数有误',{cause:'写具体错误原因'})
      6. }
      7. }
      8. try{
      9. getData()
      10. }catch(error){
      11. console.log(error,error.cause)
      12. }

      好啦!本文到此结束。若你还没有学习过ES6的新特性可以看下我之前发布的两篇文章,里面有详细且全面地介绍了ES6的新增特性!

      ES6有何新特性?(上篇)icon-default.png?t=N7T8http://t.csdnimg.cn/HJm2o

      ES6有何新特性?(下篇)icon-default.png?t=N7T8http://t.csdnimg.cn/j3Uoa

    2. 相关阅读:
      Mybatis的特性详解——四大操作标签
      GitHub Copilot 自动写代码插件使用体验
      【PAT甲级】1023 Have Fun with Numbers
      【Python】第五课 函数
      Linux常用命令
      char* s1 = new char[len + 1];这个星号是干啥的
      数字IC验证面试常见的问题汇总,你掌握了几个?
      【电源专题】LDO基础——电流限制
      JMeter接口测试
      模仿蜘蛛工作原理 苏黎世联邦理工学院研发牛油果机器人可在雨林树冠穿行
    3. 原文地址:https://blog.csdn.net/weixin_51735748/article/details/134543701