前言

ES全称ECMAScript,ECMAScript 和 JavaScript 的关系是,前者是后者的规范,后者是前者的一种实现,从15年es6发版后,到目前的es11,es的新特性被广泛使用,成为项目开发必不可少的工具,这段时间又系统的学习了这部分的相关知识,对其归纳总结,作为这段时间学习成果的检验。

ES7-ES11新特性汇总

  • ES7新特性归纳

    1. Array.prototype.includes()
      • 我们如何判断一个数组是否包含一个元素?

        熟悉es5的小伙伴会首先想到indexOf(),这个方法会返回当前数组元素的下标:

        const arr = ["es6", "es7", "es8", "es9", "es10", "es11"]
        console.log(arr.indexOf("es6"))   // 0
        console.log(arr.indexOf("es12"))  // -1
        

        亦或者:

        const item = arr.find((item) => {return item === "es6"
        })
        console.log(item)   // "es6"
        

        那么这两种方式有什么弊端呢,我们往下看:

        const arr = ["es6", "es7", "es8", "es9", "es10", "es11", NaN]
        console.log(arr.indexOf(NaN))  // -1const item = arr.find((item) => {return item === NaN
        })
        console.log(item)             // undefined
        

        由此可以看出,es5的传统方法不满足我们的需求,无法判断数组中是否含有NaN,由此,es7提供给数组一个新的API,就是我们所说的Array.prototype.includes。

      • 基本用法

        const arr = ["es6", "es7", "es8", "es9", "es10", "es11",NaN]
        console.log(arr.includes("es6"))   // true
        console.log(arr.includes(NaN))   // true
        console.log(arr.includes("es12"))  // false
        
        • Array.prototype.includes():可以接收两个参数,要搜索的值和搜索的开始索引。第二个参数可选,若为负数表示从末尾开始计数下标。
        • 只能判断简单类型的数据,对于复杂类型的数据,比如对象类型的数组,二维数组,这些是无法判断的。
      • includes的用法和indexOf用法相似,都可以用来判断数组中是否包含一个元素,唯一的区别在于includes可以识别NaN。

    2. 幂运算符
      • 我们如何求一个数的幂运算呢?

        在es5中我们可以通过以下两种方式来实现:

        // 通过Math.pow()
        console.log(Math.pow(2,53))// 自定义pow函数
        function pow(base, exponent) {let sum = 1;for (let i = 0; i <exponent; i += 1) {sum *= base}return sum
        }
        console.log(pow(2, 53));
        
      • es7提供了一种 ** 运算符,可以更简单实现

        console.log(2**53)
        
        • 幂运算符的两个*号之间不能出现空格,前后有无空格都可以。
        • 注意最大安全数:Number.MAX_SAFE_INTEGER = (2**53)-1
  • ES8新特性

    1. async/await
      1. async/await是继es6中promise、generator后又一种更加优雅的异步编程的解决方案
      2. async函数是generator函数的语法糖
      • 基本用法

        // 不使用async/await
        function getPromise() {return new Promise((resolve, reject) => {setTimeout(() => {console.log(1);resolve(2);}, 1000);});
        }function foo() {const res = getPromise();console.log(res);console.log(3);
        }foo();
        // Promise {<pending>}
        // 3
        // 1// 使用async/await
        async function foo() {const res = await getPromise();console.log(res);console.log(3);
        }foo();// 1
        // 2
        // 3

        由上面两个例子的对比就能发现,async/await可以使异步任务处理起来像是同步任务,这是因为await关键字在执行的时候会停下来,等待异步任务执行完毕(await后面一般跟的是异步任务,否则没有意义)在继续执行同步任务。

      • 更优雅的异步编程的解决方案

        在es6之前我们对于这个过程应该不陌生

        ajax('xxx/a', res => {console.log(res)ajax('xxx/b', res => {console.log(res)ajax('xxx/c', res => {console.log(res)})})
        })
        

        这种回调之后再回调的调用方式我们称之为“回调地狱”,这种回调方式在日常开发和项目维护当中很让人头疼。我们对比下es6中Promise的处理和es8中的async/await的处理方式就知道了为什么我们称async/await为更优雅的异步编程的解决方案。

        // 以下都是模拟接口请求的代码
        // Promise
        function getPromise(url) {return new Promise((resolve, reject) => {ajax(url, res => {resolve(res)}, err => {reject(err)})})
        }getPromise('xxx/a').then(res => {console.log(res)return getPromise('xxx/b')}).then(res => {console.log(res)return getPromise('xxx/c')}).then(res => {console.log(res)}).catch(err => {console.log(err)})// async/awaitfunction request(url) {return new Promise(resolve => {ajax(url, res => {resolve(res)})})
        }
        async function getData() {let res1 = await request('xxx/a')console.log(res1)let res2 = await request('xxx/b')console.log(res2)let res3 = await request('xxx/c')console.log(res3)
        }
        getData()
        

        从两者的对比可以看出,Promise虽然将回调嵌套回调的方式改成平级调用,但是这种调用方式相比于async/await还是显得繁琐,而且async/await不存在回调。

    2. Object.values()/Object.entries()
      • 我们如何获取一个对象的每一个属性值?

        在es5中我们常用Object,keys()及for in来直接获取

        // Object,keys()
        const obj = {name: "张三",age: 18,sex: "male",
        }const values = Object.keys(obj).map(item => {return obj[item]
        })
        console.log(values)   // ["张三", 18, "male"]// for in
        for (let key in obj) {console.log(obj[key])
        }
        // "张三", 18, "male"
        

        es8为我们扩展了两个新的静态方法

      • Object.values()

        Object.values() 返回一个数组,其元素是在对象上找到的可枚举属性值。

        const obj = {name: "张三",age: 18,sex: "male",
        }
        console.log(Object.values(obj)) // ["张三", 18, "male"]
        
      • Object.entries

        Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组。

        const obj = {name: "张三",age: 18,sex: "male",
        }
        console.log(Object.entries(obj))
        // [["name", "张三"],["age", "18"], ["sex", "male"]]
        
      • for in 与Object.keys()/Object.values()/Object.entries()区别

        从前面的例子可以看出for in与Object.keys()/Object.values()/Object.entries()均可以遍历对象的可枚举属性,那他们直接有什么区别呢

        const obj = {name: "张三",age: 18,sex: "male",
        }
        Object.prototype.test = "test"for (let key in obj) {console.log(obj[key])
        }
        //  "张三", 18, "male","test"
        console.log(Object.keys(obj).map(key => obj[key]))
        // ["张三", 18, "male"]
        console.log(Object.values(obj))
        // ["张三", 18, "male"]
        console.log(Object.entries(obj).map(([key, value]) => value))
        // ["张三", 18, "male"]
        

        for in可以遍历出原型链上的可枚举属性,而Object.keys()/Object.values()/Object.entries()只能遍历自身的可枚举属性

      • 如何实现一个Object.values()/Object.entries()

        const obj = {name: "张三",age: 18,sex: "male",
        }
        // Object.values
        function values(obj) {return Object.keys(obj).map(key => obj[key])
        }// Object.entries
        function entries(obj) {return Object.keys(obj).map(key => [key, obj[key]])
        }console.log(values(obj))
        console.log(entries(obj))
        
    3. Object.getOwnPropertyDescriptors()
      • 前面提到可枚举属性,我们怎么设置属性的值可枚举呢?

        Object.defineProperty()可以通过对描述符的设置进行更精准的控制对象属性,所谓描述符:

        • value [属性的值]
        • writable [属性的值是否可被改变]
        • enumerable [属性的值是否可被枚举]
        • configurable [描述符本身是否可被修改,属性是否可被删除]
        var test = {name: '测试',value: 5
        }
        Object.defineProperty(test, "name", {enumerable: false
        })for (let key in test) {console.log(key)
        }
        // value
        
      • Object.getOwnPropertyDescriptors ()

        Object.getOwnPropertyDescriptors ()可以返回对象属性的描述符

        let test = {name: '测试',value: 5
        }
        console.log(Object.getOwnPropertyDescriptors(test))
        // {
        //   name: {value: "测试", writable: true, enumerable: true, configurable: true}
        //   value: {value: 5, writable: true, enumerable: true, configurable: true}
        // }
        

        Object.getOwnPropertyDescriptors(target,param)接收两个参数,返回某一个参数的描述符,通过这个方法可以实现一个Object.getOwnPropertyDescriptors ()

      • Object.getOwnPropertyDescriptors()实现

        let test = {name: '测试',value: 5
        }function getOwnPropertyDescriptors(obj) {const result = {};for (let key of Reflect.ownKeys(obj)) {result[key] = Object.getOwnPropertyDescriptor(obj, key);}return result;
        }
        getOwnPropertyDescriptors(test)
        
    4. String.prototype.padStart()/String.prototype.padEnd()

      • padStart()

        先看一个例子,希望把当前日期格式化:yyyy-mm-dd的格式:

        // 返回一个yyyy-mm-dd格式的日期
        function getTime() {const date = new Date();const year = date.getFullYear()const month = date.getMonth() + 1const day = date.getDate()return `${year}-${month}-${day}`
        }
        console.log(getTime())
        // 2020-7-9
        

        es8 中 String 新增了两个实例函数 String.prototype.padStart() 和 String.prototype.padEnd(),允许将空字符串或其他字符串添加到原始字符串的开头或结尾。

        function getTime() {const date = new Date();const year = date.getFullYear()const month = (date.getMonth() + 1).toString().padStart(2, "0")const day = (date.getDate()).toString().padStart(2, "0")return `${year}-${month}-${day}`
        }console.log(getTime())
        // 2020-07-09
        
      • padEnd()

        在正式项目中后台返回的数据中时间一般会转为时间戳格式,处理时间戳的时候单位都是ms毫秒(13位),但有时候有可能是s秒做单位(10位),这个时候我们需要做一个13位的补全,保证单位是毫秒。

        time = String(time).padEnd(13, '0')
        
    5. 尾逗号

      此前,函数定义和调用时,都不允许最后一个参数后面出现逗号,es8 允许函数的最后一个参数有尾逗号

      // es8以前
      function foo(a, b, c, d) {console.log(a, b, c, d)
      }// es8
      function foo(a, b, c, d,) {console.log(a, b, c, d)
      }
      
  • ES9新特性

    1. for await of/Symbol.asyncIterator

      es6中有一个新特性Iteartor,只要元素符合两个协议:

      1. 可迭代协议:对象包含Symbol.iterator属性;
      2. 迭代器协议:Symbol.iterator属性必须返回一个对象,这个对象包含一个next方法,且next方法也返回一个对象,此对象包含value,done两个属性

      我们就可以使用for…of去遍历这个元素。

      • 我们知道 for…of 可以遍历同步运行的任务,那如果是异步任务呢,如下:

        function getPromise(time) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(time)}, time)})
        }const asyncArr = [getPromise(1000), getPromise(200), getPromise(3000)]for (let item of asyncArr) {console.log(item, item.then(res => {console.log(res)}))
        }
        // Promise {<pending>}
        // Promise {<pending>}
        // Promise {<pending>}
        // 200
        // 1000
        // 3000
        

        在上述遍历的过程中可以看到三个任务是同步启动的,我们期望的是一个异步任务执行完,在执行下一个异步任务,然而从输出可以看出不是按任务的执行顺序输出的,这显然不太符合我们的要求,在 es9 中也可以用 for…await…of 来操作:

        function getPromise(time) {return new Promise((resolve, reject) => {setTimeout(() => {resolve({value: time,done: false,});}, time);});
        }const asyncArr = [getPromise(1000), getPromise(200), getPromise(3000)];
        asyncArr[Symbol.asyncIterator] = function () {let nextIndex = 0;return {next() {return nextIndex < asyncArr.length? asyncArr[nextIndex++]: Promise.resolve({value: undefined,done: true,});},};
        };async function test() {for await (let item of asyncArr) {console.log(Date.now(), item);}
        }test();// 1594374685156 1000
        // 1594374685157 200
        // 1594374687157 3000
        

        await需要在async 函数或者 async 生成器里面使用

      • 同步迭代器/异步迭代器

        类别 同步迭代器 异步迭代器
        迭代器协议 Symbol.iterator Symbol.asyncIteartor
        遍历 for…of for…await…of
    2. 正则的扩展
      • dotAll/s

        一句话总结dotAll模式就是:在正则中使用(.)字符时使用s修饰符可以解决(.)字符不能匹配行终止符的例外

        console.log(/./.test(1));
        console.log(/./.test("1"));
        console.log(/./.test("\n"));
        console.log(/./.test("\r"));
        console.log(/./.test("\u{2028}"));
        // true
        // true
        // false
        // false
        // false// 使用s修饰符
        console.log(/./s.test(1));
        console.log(/./s.test("1"));
        console.log(/./s.test("\n"));
        console.log(/./s.test("\r"));
        console.log(/./s.test("\u{2028}"));
        // true
        // true
        // true
        // true
        // true
        
        1. (.)是一个特殊字符,代表任意的单个字符,但是有两个例外。一个是四个字节的 UTF-16 字符,这个可以用u修饰符解决;另一个是行终止符
        2. 正则中可以使用的修饰符有i,g,m,y,u,s
      • 具名组匹配

        我们先看一个例子

        console.log("2020-07-10".match(/(\d{4})-(\d{2})-(\d{2})/));
        // ["2020-07-10", "2020", "07", "10", index: 0, input: "2020-07-10", groups: undefined]
        

        按照 match 的语法,没有使用 g 修饰符,所以返回值第一个数值是正则表达式的完整匹配,接下来的第二个值到第四个值是分组匹配(2020, 07, 10),我们想要获取年月日的时候不得不通过数组的下标去获取,这样显得不灵活。仔细观察 match 返回值还有几个属性,分别是 index、input、groups。

        1. index [匹配的结果的开始位置]
        2. input [匹配的字符串]
        3. groups [捕获组 ]

        所谓的具名组匹配就是命名捕获分组:

        console.log("2020-07-10".match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/));// groups的值
        groups: {year: "2020", month: "07", day: "10"}
        

        这样我们就可以通过groups及命名分组获取对应的年月日的值了。

      • 后行断言

        let test = 'world hello'
        console.log(test.match(/(?<=world\s)hello/))
        

        (?<)是后行断言的符号配合= 、!等使用。

    3. 对象的Rest和Spread语法
      • 一个例子对比理解对象的Rest和Spread语法

        const arr1 = [1, 2, 3];
        const arr2 = [4, 5, 6];// 数组合并
        const arr = [...arr1, ...arr2];
        console.log(arr);const obj1 = { a: 1 };
        const obj2 = { b: 2 };// 对象合并
        const obj = { ...obj1, ...obj2 };
        console.log(obj);// [1, 2, 3, 4, 5, 6]
        // {a: 1, b: 2}
        

        一句话总结就是(…)运算符在数组中可以怎样使用,在对象就可以怎样使用。

    4. Promise.prototype.finally()
      • 不管promise状态如何都会执行的回调函数

        new Promise((resolve, reject) => {resolve(1);
        }).then((res) => {console.log(res);}).catch((err) => {console.log(err);}).finally(() => {console.log("finally");});
        // 1
        // promise
        
    5. 带标签的模板字符串扩展

      es9 新特性中移除了对 ECMAScript带标签的模板字符串中转义序列的语法限制。 遇到不合法的字符串转义返回undefined,并且从raw上可获取原字符串

      function foo(str) {console.log(str);
      }foo`\undfdfdf`;
      // es9以前报错
      // es9:[undefined, raw:["\undfdfdf"]]
      
  • ES10新特性

    1. Object.fromEntries()

      es8中对象添加了一个entries()静态方法,这个方法返回一个给定对象自身可枚举属性的键值对数组 ,Object.fromEntries()方法与 Object.entries() 正好相对,可以将键值对列表转换为一个对象 。

      const obj = {x: 1,y: 2,
      };const entries = Object.entries(obj);console.log(entries);
      console.log(Object.fromEntries(entries));// [["x",1],["y":2]]
      // {x:1,y:2}
      

      只要符合entries结构的都可以使用Object.fromEntries(entries)将键值对列表转换为一个对象,比如Map

    2. String.prototype.trimStart()/String.prototype.trimEnd()
      • trimStart() /trimLeft()

        trimLeft是trimStart的别名,作用是去掉字符串左边的空格

      • trimEnd() / trimRight()

        trimEnd是trimRight的别名,作用是去掉字符串右边的空格

      const str = "   hello world   ";
      console.log(str.trimStart());
      console.log(str.trimEnd());
      console.log(str.trim());// "hello world   "
      // "   hello world"
      // "hello world"
      
    3. Array.prototype.flat()/Array.prototype.flatMap()
      • Array.prototype.flat()

        flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回 。

        const arr = [1, [2, [3, [4, [5, [6, 7], 8], 9]]]];
        console.log(arr.flat(1));
        console.log(arr.flat(5));
        console.log(arr.flat(Infinity));// [1,2,[3, [4, [5, [6, 7], 8], 9]]]
        // [1,2,3,4,5,6,7,8,9]
        // [1,2,3,4,5,6,7,8,9]
        
      • 自定义实现flat

        function flat(arr, deep = 1) {const newArray = [];let deepNum = 0;const flatMap = (arr) => {arr.map((item, index, array) => {if (Array.isArray(item)) {if (deepNum < deep) {deepNum++;flatMap(item);} else {newArray.push(item);}} else {newArray.push(item);if (index === array.length - 1) deepNum = 0;}});};flatMap(arr);return newArray;
        }const arr = [1, [2, [3, [4, [5, 6], 7], 8]]];
        console.log(flat(arr, 4));
        
      • Array.prototype.flatMap()

        flatMap实质上包含两部分功能,一是map,二是flat

        const numbers = [1, 2, 3];console.log(numbers.map((x) => [x ** 2]).flat());
        console.log(numbers.flatMap((x) => [x ** 2]));// [1,4,9]
        // [1,4,9]
        
    4. Symbol.description
      • 可以通过 description 获取 Symbol 的描述

        const symbol = Symbol("symbol");
        console.log(symbol.description); // symbol
        console.log(symbol.description === "symbol"); // true
        

        在es10以前,我们只能通过调用 Symbol 的 toString() 时才可以读取这个属性

        console.log(symbol.toString() === "Symbol(symbol)");
        
    5. Function.prototype.toString()
      • Function.prototype.toString() 方法返回一个表示当前函数源代码的字符串

        function test(a) {// es10以前不返回注释部分console.log(a);
        }
        console.log(test.toString());// function test(a) {
        //  // es10以前不返回注释部分
        //  console.log(a);
        // }
        
    6. catch Building
      • es10允许我们在捕获异常时省略catch的参数

        // es10以前
        try {throw new Error();
        } catch (error) {console.log("fail");
        }// es10
        try {throw new Error();
        } catch {console.log("fail");
        }
        
    7. JSON扩展
      • JSON 内容可以支持包含 U+2028行分隔符 与 U+2029段分隔符

      • 在 ES10 JSON.stringify 会用转义字符的方式来处理 超出范围的 Unicode 展示错误的问题 而非编码的方式

        console.log(JSON.stringify('\uD83D\uDE0E')) // 笑脸// 单独的\uD83D其实是个无效的字符串
        // 之前的版本 ,这些字符将替换为特殊字符,而现在将未配对的代理代码点表示为JSON转义序列
        console.log(JSON.stringify('\uD83D')) // "\ud83d"
        
  • ES11新特性

    1. BigInt

      es11为我们提供了第七种新的原始数据类型,对于js来说,他的最大取值范围是2的53次方

      console.log(2 ** 53);
      console.log(2 ** 53 + 1);
      console.log(Number.MAX_SAFE_INTEGER);
      // 9007199254740992
      // 9007199254740992
      // 9007199254740991
      

      BigInt,表示一个任意精度的整数,可以表示超长数据,可以超出2的53次方 。

      • 使用方式

         // 方式一console.log(9007199254740993);console.log(9007199254740993n);// 9007199254740992// 9007199254740993n// 方式二console.log(9007199254740993);console.log(BigInt(9007199254740993n));// 9007199254740992// 9007199254740993n
        
        1. 1==1n // true
        2. 1 === 1n // false
        3. typeof 1n // bigint
        4. BigInt(9007199254740993n).toString() // 9007199254740993
        
        
    2. 可选链

      可选链可以使我们在查询具有多层级的对象时,不再需要进行冗余的各种前置校验。

      const a = {b: {c: {d: {e: "111",},},},
      };// es11前
      const value = a && a.b && a.b.c && a.b.c.d && a.b.c.d.e;
      console.log(value);// es11:可选链
      const value2 = a?.b?.c?.d?.e;
      console.log(value2);
      

      可选链中的 ? 表示如果问号左边表达式有值, 就会继续查询问号后面的字段 , 可以大量简化类似繁琐的前置校验操作 。

    3. 空值合并运算符

      当我们查询某个属性时,经常会遇到,如果没有该属性就会设置一个默认的值。

      const a = 0;
      const b = a || 1;
      console.log(b);// 1
      

      我们在使用||运算符时, 变量值为 0 就是 false ,所以我们会看到上述结果会输出1,但是很多时候我们希望b的输出结果就是a的值0,es11提出了空值合并运算符(??),当左侧操作数为 null 或 undefined 时,其返回右侧的操作数。否则返回左侧的操作数。

      const a = 0;
      const b = a ?? 1;
      console.log(b);// 0
      
    4. Promise.allSettled()

      es6中 Promise.all方法接受一个数组元素都是由 Promise.resolve 包装的数组, 生成并返回一个新的 Promise 对象, 如果参数中的任何一个promise为reject的话,则整个Promise.all调用会立即终止,并返回一个reject的新的 Promise 对象。

      // 全部返回resolve
      function getPromise(time) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(time);}, time);});
      }Promise.all([getPromise(1000), getPromise(2000), getPromise(3000)]).then((res) => {console.log(res);}
      );// [1000,2000,3000]// 返回reject
      function getPromise(time) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(time);}, time);});
      }function getReject(time) {return new Promise((resolve, reject) => {setTimeout(() => {reject(time);}, time);});
      }Promise.all([getPromise(1000), getReject(2000), getPromise(3000)]).then((res) => {console.log(res);}).catch((err) => {console.log(err);});// 2000
      

      从上面可以看出Promise.all只要有一个任务返回reject,整个任务都会失败, 我们需要一种机制,如果并发任务中,无论一个任务正常或者异常,都会返回对应的的状态 ,这就是Promise.allSettled()的作用。

      function getPromise(time) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(time);}, time);});
      }function getReject(time) {return new Promise((resolve, reject) => {setTimeout(() => {reject(time);}, time);});
      }Promise.allSettled([getPromise(1000), getReject(2000), getPromise(3000)]).then((res) => {console.log(res);}).catch((err) => {console.log(err);});// [{status: "fulfilled", value: 1000},
      //  {status: "rejected", reason: 2000},
      //  {status: // "fulfilled", value: 3000}]
      
    5. import
      • 按需加载

        现代前端打包资源越来越大,打包成几M的JS资源已成常态,而往往前端应用初始化时根本不需要全量加载逻辑资源,为了首屏渲染速度更快,很多时候都是按需加载,比如懒加载图片等。

        (async () => {if (somethingIsTrue) {// import module for side effectsawait import('xxx/xxx.js');}
        })();
        
    6. String.prototype.matchAll()
      1. matchAll() 方法返回一个包含所有匹配正则表达式及分组捕获结果的迭代器 ;
      2. 使用: str.matchAll(regexp) ;

      字符串处理的一个常见场景是想要匹配出字符串中的所有目标子串,例如:

      • match()

        const str ="es2015/es6 es2016/es7 es2017/es8 es2018/es9 es2019/es10 es2020/es10";
        console.log(str.match(/(es\d+)\/es(\d+)/g));
        // ["es2015/es6", "es2016/es7", "es2017/es8", "es2018/es9", "es2019/es10", //"es2020/es10"]
        

        match()方法中,正则表达式所匹配到的多个结果会被打包成数组返回,但无法得知每个匹配除结果之外的相关信息,比如捕获到的子串,匹配到的index位置等 。

      • exec ()

      const str ="es2015/es6 es2016/es7 es2017/es8 es2018/es9 es2019/es10 es2020/es10";
      const reg = /(es\d+)\/es(\d+)/g;
      let matched;
      let formatted = [];
      while ((matched = reg.exec(str))) {formatted.push(`${matched[1]}-es${matched[2]}`);
      }
      console.log(formatted);//["es2015-es6","es2016-es7","es2017-es8","es2018-es9","es2019-es10",
      //"es2020-es10"]
      
      • matchAll()

        const str ="es2015/es6 es2016/es7 es2017/es8 es2018/es9 es2019/es10 es2020/es10";
        const reg = /(es\d+)\/es(\d+)/g;const matchs = [];
        for (let match of str.matchAll(reg)) {matchs.push(`${match[1]}-es${match[2]}`);
        }
        console.log(matchs);
        //  ["es2015-es6", "es2016-es7", "es2017-es8", "es2018-es9", "es2019-es10", "es2020-es10"]
        

        matchAll() 是返回一个迭代器,对大数据量的场景更友好 。

    7. globalThis

      Javascript 在不同的环境获取全局对象有不通的方式:

      • node 中通过 global,
      • web 中通过 window, self 。

      es11提出的globalThis一句话总结就是: 无论是在node环境还是web中,全局作用域中的 this 可以通过globalThis访问, 不必担心它的运行环境 。

    8. for…in遍历机制

      JavaScript 中通过for-in遍历对象时 key 的顺序是不确定的,因为规范没有明确定义,并且能够遍历原型属性让for-in的实现机制变得相当复杂,不同 JavaScript 引擎有各自根深蒂固的不同实现,很难统一

      • 所以 es11不要求统一属性遍历顺序,而是对遍历过程中的一些特殊 Case 明确定义了一些规则:
      • 遍历不到 Symbol 类型的属性
      • 遍历过程中,目标对象的属性能被删除,忽略掉尚未遍历到却已经被删掉的属性
      • 遍历过程中,如果有新增属性,不保证新的属性能被当次遍历处理到
      • 属性名不会重复出现(一个属性名最多出现一次)
      • 目标对象整条原型链上的属性都能遍历到

相关文档:

  • 新特性概览

ES7-ES11新特性汇总相关推荐

  1. ES6/ES7/ES8新特性汇总

    ES6起各个版本的新特性汇总 ES全称ECMAScript,ECMAScript是ECMA制定的标准化脚本语言.目前JavaScript使用的ECMAScript版本为ECMA-417.关于ECMA的 ...

  2. ES7、ES8、ES9、ES10、ES11 新特性 总结

    目录 ES7新特性 一.Array.prototype.includes 二.指数操作符 ES8新特性 一.async 和 await 1.async 函数 2.await 表达式 async和awa ...

  3. 七月学习之E6、ES7、ES8、ES9、ES10、ES11新特性

    目录 ES6新特性(2015) 1. let 和 const 命令 2. 解构赋值 3. 扩展运算符(spread) 4. 箭头函数 5. 函数参数默认值 6. 模板字符串 7. 对象属性和方法的简写 ...

  4. ES7、ES8、ES9、ES10、ES11新特性

    一.ES7新特性 1. Array.prototype.includes includes 方法用来检测数组中是否包含某个元素,返回布尔值 2. 指数操作符 指数运算符 ** ,用来实现幂运算,功能与 ...

  5. oracle12c 新特性,12c Oracle数据库新特性汇总

    12c Oracle数据库新特性汇总 中文社区 (MOSC) 数据库 (MOSC) 8 Replies Last updated on February 15, 2017 12c Oracle数据库有 ...

  6. Oracle 21C 新特性:数据泵相关新特性汇总

    墨墨导读:本文来自墨天轮用户"JiekeXu"投稿,墨天轮主页:https://www.modb.pro/u/434,本文分享Oracle 21c 新特性:数据泵相关新特性汇总. ...

  7. coreldraw x7 分布_CorelDRAW X7新特性汇总

    这篇教程是向大家介绍CorelDRAW X7新特性汇总,教程很不错,推荐过来,喜欢的朋友一起来学习吧 CorelDRAW X7新特性 一. 轻松启动和运行 CorelDRAW Graphics Sui ...

  8. android l 新功能,Android L怎么样 安卓L新特性汇总

    在刚刚结束的2014谷歌IO大会上,谷歌共发布了8款新品,其中Android L成为发布会的一大看点.此次谷歌并没有将新安卓系统命名为Android 5.0,而是命名为Android L.仅从命名来看 ...

  9. jdk8 新特性汇总

    jdk8 新特性汇总 1.掌握Lambda表达式的基本用法以及省略模式 2.掌握接口中新增的静态方法跟默认方法的使用 3.掌握函数接口的用法 4.掌握方法引用的使用 5.掌握Stream流在集合中的使 ...

最新文章

  1. MySQL 备份和恢复策略
  2. CentOS LVM
  3. [深入理解Android卷一全文-第九章]深入理解Vold和Rild
  4. 为何gpio_to_irq不能静态使用?【转】
  5. 奇妙的安全旅行之MD算法
  6. mysql抖动可能的原因_MySQL应对网络抖动问题
  7. jni c 回调 java,JNI - 如何从C ++或C回调到Java?
  8. android在github上调用aar文件
  9. PHP连数据库生成数据字典
  10. FPGA:生成占空比可调的PWM波
  11. 智能工厂具体的名词解释
  12. java --help_java help
  13. 【數論】【搜索】【SCOI2009】遊戲
  14. Python练习:四叶玫瑰数求解
  15. 【菜菜子力扣刷题】1.两数之和
  16. TP50 TP90 TP95 TP99 TP999 TP9999
  17. C Primer Plus中文 第6版勘误表
  18. SwiftUI iOS 精品完成项目之宠物展示与领养App MVVM(教程含源码)
  19. [offer收割]编程联系赛2-A 买零食
  20. 新中新DKQ-A16D身份证读卡器C#对接程序出坑记

热门文章

  1. centos系统mysql数据库搭建教程
  2. java实现图片上传至本地
  3. Nmap常用命令及扫描原理
  4. python读写、创建文件、文件夹
  5. WebRequest 类
  6. chapter-13-生成式模型
  7. swipecell样式_反馈组件 SwipeCell 滑动单元格 - 闪电教程JSRUN
  8. MFC中添加GIF图片
  9. TCP协议-TCP的拥塞控制
  10. 360个人图书馆禁止复制问题