ES7-ES11新特性

1,610 阅读3分钟

ECMASript 7 新特性

Array.prototype.includes

Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值

指数操作符

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

<script>
    // includes与indexOf有区别,indexOf在存在时返回下标,不存在则返回-1
    // includes返回boolean值,写代码更方便
    const mingzhu = ['A','B','C','D'];

    //判断
    console.log(mingzhu.includes('A'));//true
    console.log(mingzhu.includes('E'));//false

    // **
    console.log(2 ** 10);// 1024
    console.log(Math.pow(2, 10));

</script>

ECMASript 8 新特性

async 和 await

async 和 await 两种语法结合可以让异步代码像同步代码一样

async 函数

1. async 函数的返回值为 promise 对象

2. promise 对象的状态结果由 async 函数执行的返回值决定

<script>
    //async 函数
    async function fn(){
        // 返回一个字符串,返回的结果就是成功 Promise对象
        return '葡葡';
        // 返回的结果不是一个 Promise 类型的对象, 返回的结果就是成功 Promise对象
        return;//直接return不跟值,其实返回的是undefined
        //抛出错误, 返回的结果是一个失败的 Promise对象
        throw new Error('出错啦!');
        //返回的结果如果是一个 Promise 对象
        return new Promise((resolve, reject)=>{
            resolve('成功的数据');
            reject("失败的错误");
        });
    }

    const result = fn();

    //调用 then 方法
    result.then(value => {
        console.log(value);
    }, reason => {
        console.warn(reason);
    })
</script>

await 表达式

1. await 必须写在 async 函数中

2. await 右侧的表达式一般为 promise 对象

3. await 返回的是 promise 成功的值

4. await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理

<script>
    //创建 promise 对象
    const p = new Promise((resolve, reject) => {
        // resolve("用户数据");
        reject("失败啦!");
    })

    // await 要放在 async 函数中.
    async function main() {
        try {
            let result = await p;//await返回的是成功的PromiseResult值
            console.log(result);//用户数据
        } catch (e) {
            console.log(e);//catch的是失败的PromiseResult值
        }
    }
    //调用函数
    main();
</script>

async 和 await 结合读取文件

//1. 引入 fs 模块
const fs = require("fs");

//读取『为学』
function readWeiXue() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/为学.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

function readChaYangShi() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/插秧诗.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

function readGuanShu() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/观书有感.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

//声明一个 async 函数
async function main(){
    //获取为学内容
    let weixue = await readWeiXue();
    //获取插秧诗内容
    let chayang = await readChaYangShi();
    // 获取观书有感
    let guanshu = await readGuanShu();

    console.log(weixue.toString());
    console.log(chayang.toString());
    console.log(guanshu.toString());
}

main();

async 与 await 封装AJAX请求

<script>
// 发送 AJAX 请求, 返回的结果是 Promise 对象
function sendAJAX(url) {
    return new Promise((resolve, reject) => {
        //1. 创建对象
        const x = new XMLHttpRequest();

        //2. 初始化
        x.open('GET', url);

        //3. 发送
        x.send();

        //4. 事件绑定
        x.onreadystatechange = function () {
            if (x.readyState === 4) {
                if (x.status >= 200 && x.status < 300) {
                    //成功啦
                    resolve(x.response);
                }else{
                    //如果失败
                    reject(x.status);
                }
            }
        }
    })
}

//promise then 方法测试
sendAJAX("https://api.apiopen.top/getJoke").then(value=>{
    console.log(value);
}, reason=>{})

// async 与 await 测试  axios
async function main(){
    //发送 AJAX 请求
    let result = await sendAJAX("https://api.apiopen.top/getJoke");
    //再次测试
    let tianqi = await sendAJAX('https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P')

    console.log(tianqi);
}

main();

</script>

Object.values 和 Object.entries

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

2. Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组

Object.getOwnPropertyDescriptors

该方法返回指定对象所有自身属性的描述对象

<script>
    //声明对象
    const school = {
        name:"葡葡",
        cities:['皮皮','秋秋','小皮小葡'],
        xueke: ['前端','Java','大数据','运维']
    };

    //获取对象所有的键
    console.log(Object.keys(school));
    //获取对象所有的值
    console.log(Object.values(school));
    //entries:将一个对象转化为一个二维数组
    console.log(Object.entries(school));
    // [
    //   ["name", "葡葡"],
    //   ["cities", ['皮皮','秋秋','小皮小葡']],
    //   ["xueke", ['前端','Java','大数据','运维']]
    // ]
    
    //创建 Map
    const m = new Map(Object.entries(school));
    console.log(m.get('cities'));// ['皮皮','秋秋','小皮小葡']
    console.log(m);
    //打印结果为  [ 
    //               { "name" => "葡葡" },
    //               { "cities" => ['皮皮','秋秋','小皮小葡']},
    //               { "xueke" => ['前端','Java','大数据','运维']} 
    //          ]
    

    // Object.getOwnPropertyDescriptors对象属性的描述对象
    // Object.getOwnPropertyDescriptors返回的是下面那个Object.create的第二个参数,即描述对象
    console.log(Object.getOwnPropertyDescriptors(school));

    // Object.create的第一个参数是原型对象,第二个参数是描述对象
    const obj = Object.create(null, {
        name: {
            //设置值
            value: '葡葡',
            //属性特性
            writable: true,
            configurable: true,
            enumerable: true
        } 
    });
</script>

ECMASript 9 新特性

Rest/Spread 属性

Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符

 <!-- 
    Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,
    在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符
 -->
<script>
    //rest 参数
    function connect({host, port, ...user}){
        console.log(host);
        console.log(port);
        console.log(user);
    }

    connect({
        host: '127.0.0.1',
        port: 3306,
        username: 'root',
        password: 'root',
        type: 'master'
    });


    //对象合并
    const skillOne = {
        q: '钱钱'
    }

    const skillTwo = {
        w: '哇哇'
    }

    const skillThree = {
        e: '天天'
    }
    const skillFour = {
        r: '绵绵'
    }

    const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};

    console.log(mangseng)

    // ...skillOne   =>  q: '钱钱', w: '哇哇'

</script>

正则表达式命名捕获组

ES9 允许命名捕获组使用符号『?』 ,这样获取捕获结果可读性更强

//声明一个字符串
let str = '<a href="http://www.baidu.com">葡葡逆风翻盘</a>'; 

//旧方法:提取 url 与 『标签文本』
const reg1 = /<a href="(.*)">(.*)<\/a>/;
//执行
const result1 = reg.exec(str1); 
console.log(result1[1]);//http://www.baidu.com
console.log(result1[2]);//葡葡逆风翻盘

//ES9:分组命名
const reg2 = /<a href="(?<url>.*)">(?<text>.*)<\/a>/; 
//执行
const result2 = reg.exec(str2); 
console.log(result2.groups.url);//http://www.baidu.com
console.log(result2.groups.text);//葡葡逆风翻盘

正则表达式反向断言

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

//声明字符串 
let str = 'JS5211314 你知道么 555 啦啦啦'; 
//正向断言:根据后面内容“啦”判断前面内容是否合法\d+
const reg = /\d+(?=啦)/; 
const result = reg.exec(str); 
console.log(result);//555
//反向断言:根据前面内容“么”判断后面内容是否合法\d+ 
const reg = /(?<=么)\d+/;
const result = reg.exec(str); 
console.log(result);//555

正则表达式 dotAll 模式

正则表达式中点.匹配除回车外的任何单字符,标记『s』 改变这种行为,允许行终止符出现

let str = ` 
<ul> 
    <li> 
        <a>肖生克的救赎</a> 
        <p>上映日期: 1994-09-10</p> 
    </li> 
    <li> 
        <a>阿甘正传</a> 
        <p>上映日期: 1994-07-06</p> 
    </li> 
</ul>`; 
//需求:把标签里的内容存入数组对象里
//声明正则 
// const reg = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/;旧方法
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs; 
//执行匹配 
//const result = reg.exec(str); 
let result;
let data = []; 
while(result = reg.exec(str)){
    data.push({title: result[1], time: result[2]});
} 
//输出结果 
console.log(data); 

ECMASript 10 新特性

Object.fromEntries将二维数组转化为对象

用于创建一个对象

<script>
    //二维数组
    const result = Object.fromEntries([
        ['name','葡葡'],
        ['xueke', 'Java,大数据,前端,云计算']
    ]);
    console.log(result);
    //打印结果:{name:"葡葡", xueke: "Java,大数据,前端,云计算"}

    //Map
    const m = new Map();
    m.set('name','PUPU');
    const result = Object.fromEntries(m);
     console.log(result);
     //打印结果:{name:"PUPU"}

    //Object.entries ES8将对象转化为二维数组
    const arr = Object.entries({
        name: "葡葡皮皮"
    })
    console.log(arr);
     //打印结果:[[name, "葡葡皮皮"]]
     
</script>

trimStart 和 trimEnd

<script>    
    let str = '   iloveyou   ';
    console.log(str);
    // trim清除字符串空白字符
    console.log(str.trim());
    // trimStart清除字符串左侧空白字符
    console.log(str.trimStart());
    // trimEnd清除字符右左侧空白字符
    console.log(str.trimEnd());
</script>

Array.prototype.flat 与 flatMap

<script>
    //flat 平
    //将多维数组转化为低位数组
    const arr = [1,2,3,4,[5,6]];
    console.log(arr.flat());//[1,2,3,4,5,6]
    const arr = [1,2,3,4,[5,6,[7,8,9]]];
    //参数为深度 是一个数字 不传默认是1
    console.log(arr.flat(2));  

    //flatMap
    //是两个操作的结合,map遍历,flat铺平,多维降为一维
    const arr = [1,2,3,4];
    const result = arr.flatMap(item => [item * 10]);
    console.log(result);//[10,20,30,40]
</script>

Symbol.prototype.description

用来获取Symbol的描述字符串

<script>
    //创建 Symbol
    let s = Symbol('葡葡');
    console.log(s.description); //葡葡 
    
</script>

ECMASript 11 新特性

类的私有属性

<script>
    class Person{
        //公有属性
        name;
        //私有属性
        #age;
        #weight;
        //构造方法
        constructor(name, age, weight){
            this.name = name;
            this.#age = age;
            this.#weight = weight;
        }

        intro(){
            console.log(this.name);
            console.log(this.#age);//88
            console.log(this.#weight);//100kg
        }
    }

    //实例化
    const dd = new Person('AA', 88, '100kg');

    console.log(dd.name);
    console.log(dd.#age);//报错
    console.log(dd.#weight);//报错

    girl.intro();
</script>

Promise.allSettled

Promise.allSettled 与 Promise.all ,都应用于批量处理异步任务的一个场景

Promise.allSettled 接受promise数组,返回promise对象,且其结果状态永远成功

<script>
    //声明两个promise对象
    const p1 = new Promise((resolve, reject)=>{
        setTimeout(()=>{
            resolve('商品数据 - 1');
        },1000)
    });

    const p2 = new Promise((resolve, reject)=>{
        setTimeout(()=>{
            // resolve('商品数据 - 2');
            reject('出错啦!');
        },1000)
    });

    //调用 allsettled 方法,接受promise数组
    const result = Promise.allSettled([p1, p2]);
    //返回promise对象,且其结果状态永远成功。就算p2是reject
    console.log(result);
    
    const res = Promise.all([p1, p2]);
     //返回promise对象,且其结果状态由p1p2决定,都成功才成功 
    console.log(res);

</script>

String.prototype.matchAll

String.prototype.matchAll 方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。

<script>
    let str = `<ul>
        <li>
            <a>肖生克的救赎</a>
            <p>上映日期: 1994-09-10</p>
        </li>
        <li>
            <a>阿甘正传</a>
            <p>上映日期: 1994-07-06</p>
        </li>
    </ul>`;

    //声明正则
    const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg

    //调用方法
    const result = str.matchAll(reg);//返回一个可迭代对象
    
    //对其用for of,可以很方便拿到数组
    for(let v of result){
        console.log(v);
    }

     //对其用...,可以很方便拿到数组
    const arr = [...result];

    console.log(arr);

</script>

可选链操作符 ?.

<script>
    // ?.
    function main(config){
        // const dbHost = config && config.db && config.db.host;
        // 层层判断太麻烦了,于是 ?.
        const dbHost = config?.db?.host;

        console.log(dbHost);
    }

    main({
        db: {
            host:'192.168.1.100',
            username: 'root'
        },
        cache: {
            host: '192.168.1.200',
            username:'admin'
        }
    })
</script>

动态 import 导入

ES6模块化里的 import 是静态的,即不能实现懒加载、按需加载

此处的动态 import 可实现懒加载、按需加载,提高加载效率

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动态 import </title>
</head>
<body>
    <button id="btn">点击</button>
    <script src="./js/app.js" type="module"></script>
</body>
</html>
//app.js
// import * as m1 from "./hello.js";
//获取元素
const btn = document.getElementById('btn');

btn.onclick = function(){
    // 动态 import,返回的是promise对象 
    import('./hello.js').then(module => {
        module.hello();
    });
}
//hello.js
export function hello(){
    alert('Hello');
}

BigInt

把普通值转换成大整型值

<script>
    //大整型
    let n = 521n;
    console.log(n, typeof(n));//521n  "bigint"

    //函数
    let n = 123;
    console.log(BigInt(n));//123n
    console.log(BigInt(1.2));//不可用浮点型来转,会报错

    //运用于:大数值运算
    let max = Number.MAX_SAFE_INTEGER;
    console.log(max);
    console.log(max + 1);
    console.log(max + 2);//此时数值已经无法再增大

    console.log(BigInt(max))
    console.log(BigInt(max) + BigInt(1));
    console.log(BigInt(max) + BigInt(2));//此时数值可以再增大
</script>

globalThis 对象

始终指向全局对象

//globalThis.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>globalThis</title>
</head>
<body>
    <script>
        console.log(globalThis);//window对象
    </script>
</body>
</html>
//globalThis.js
console.log(globalThis);//Object [global]