1.ES6:Generator函数

  • 概述

    • 该函数是 ES6 提供的一种异步编程解决方案
    • 该函数是一个状态机,封装了多个内部状态
    • 执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数,返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态
  • 基本用法

    function *gen(){
        console.log(1);
        yield; // 产出
        console.log(2);
        yield;
        console.log(3);
    }
    
    let g = gen();
    g.next();
    g.next();
    g.next();
    

image-20230810204811619.png

yield(产出)表达式是暂停执行的标记,而 next 方法可以恢复执行

  function *gen(){
      yield 1;
      yield 2;
  }

  let g = gen();

  let res1 = g.next();
  console.log(res1);
  let res2 = g.next();
  console.log(res2);
  let res3 = g.next();
  console.log(res3);

image-20230810204818229.png

  function *gen(){
      let res1 = yield "aaa";
      console.log(res1);
      let res2 = yield "bbb";
      console.log(res2);
  }
  let g = gen();

  let res1 = g.next("参数-111");
  console.log(res1);
  let res2 = g.next("参数-222");
  console.log(res1);
  let res3 = g.next("参数-333");
  console.log(res1);

image-20230810204824749.png

  • 异步流程【手动】

    function ajax(url){
        return new Promise((resolve,reject) => {
            let xhr = new XMLHttpRequest();
            xhr.open("get",url,true);
            xhr.send();
            xhr.onreadystatechange = function(){
                if(xhr.status >= 200 && xhr.status < 300){
                    resolve(JSON.parse(xhr.responseText));
                }else{
                    reject(xhr.responseText);
                }
            }
        })
    }
    
    function *gen(){
        let res1 = yield ajax("1.json");
        console.log(res1);
        let res2 = yield ajax("2.json");
        console.log(res2);
    }
    let g = gen();
    
    g.next().value.then(data => {
        g.next(data).value.then(data => {
            g.next(data);
        })
    })
    
  • 异步流程【自动】

    function *gen(){
        let res1 = yield ajax("1.json");
        console.log(res1);
        let res2 = yield ajax("2.json");
        console.log(res2);
    }
    function AutoRun(gen) {
        let g = gen();
            function next(data) {
                let res = g.next(data);
                if (res.done) return
                res.value.then(function (data) {
                    next(data);
                });
            }
        next();
    }
    AutoRun(gen);
    

2.ES6:Class

  • 类的写法

    class Person{
        constructor(name,age){
            this.name = name;
            this.age = age;
        }
        say(){
            console.log(this.name,this.age);
        }
    }
    let obj = new Person("haonan",100);
    console.log(obj);
    
  • getter、setter

    class List{
        constructor(ele){
            this.element = ele
        }
        get html(){
            return this.element.innerHTML;
        }
        set html(arr){
            this.element.innerHTML = arr.map(item = > `<li>${item}</li>`).join("");
        }
    }
    let obj = new List(document.querySelector("#list"))
    
    obj.html = ["aaa","bbb","ccc"];
    

    不能在进行构造函数的时候也设置了get set已有的属性,因为此处的get set只是为了得到某个属性值或者设置某个属性值做的拦截和相应逻辑处理【与Java不同】

  • 静态属性和静态方法

    class Person{
        static name = "Person类";
        constructor(name,age){
            this.name = name;
            this.age = age;
        }
        say(){
            console.log(this.name,this.age);
        }
        static eat(){
            console.log("eat");
        }
    }
    console.log(Person.name);
    Person.eat();
    
  • 继承

    ES6 规定,子类必须在 constructor()方法重调用super(),否则就会报错。同理 Java 继承

    class Person{
        static name = "Person类";
        constructor(name,age){
            this.name = name;
            this.age = age;
        }
        say(){
            console.log(this.name,this.age);
        }
        static eat(){
            console.log("eat");
        }
    }
    class Student extends Person{
        constructor(name,age,score){
            super(name,age);
            this.score = score;
        }
        say(){
            super.say();
            console.log(this.score);
        }
    }
    let student = new Student("haonan",22,100);
    console.log(student);
    student.say();
    // 调用静态方法
    Student.eat();
    
  • 使用场景,通过对象的形式接收参数渲染

    <body>
        <div class="box1">
            <h1></h1>
            <ul></ul>
        </div>
        <div class="box2">
            <h1></h1>
            <img src="" alt="" style="width: 100px;">
            <ul></ul>
        </div>
        <script>
            var data1 = {
                title: "体育",
                list:["体育-1","体育-2","体育-3"]
            }
    
            class CreateBox{
                constructor(select,data){
                    this.ele = document.querySelector(select);
                    this.title = data.title;
                    this.list = data.list;
                }
                render(){
                    let h1 = this.ele.querySelector("h1");
                    let ul = this.ele.querySelector("ul");
    
                    h1.innerHTML = this.title;
                    ul.innerHTML = this.list.map(item => `<li>${item}</li>`).join("");
                }
            }
            new CreateBox(".box1",data1).render();
    
            let data2 = {
                title: "综艺",
                url:"https://pic.maizuo.com/usr/movie/5011ee407fb407d47e333a3935ec33d1.jpg?x-oSs-process=image/ quality,0_70",
                list: ["综艺-1","综艺-2","综艺-3"]
            }
    
            class CreateImgBox extends CreateBox{
                constructor(select,data){
                    super(select,data);
                    this.imgURL = data.url;
                }
                render(){
                    super.render();
                    let img = this.ele.querySelector("img");
                    img.src = this.imgURL;
                }
            }
            new CreateImgBox(".box2",data2).render();
        </script>
    </body>
    

3.ES6:module模块化

ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,再通过 import 命令输入

  • 用法

    • 1.js
    console.log(document.querySelector("div"));
    
    function A1(){
        console.log("1.js——A1");
    }
    
    function A2(){
        console.log("1.js——A2");
    }
    
    function test(){
        console.log("1.js——test");
    }
    
    export default {
        A1,
        A2,
        test
    }
    
    • 2.js
    function B1(){
        console.log("2.js——B1");
    }
    
    function test(){
        console.log("2.js——test");
    }
    
    export default {
        B1,
        test
    }
    
    • 3.js
    
    // 调用1.js中的A1  和2.js中的B1
    import obj1 from "./1.js"
    import obj2 from "./2.js"
    obj1.A1();
    obj2.B1();
    
    export default{
    
    }
    
    • html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <!-- <script src="./1.js" type="module"></script>  这种方式虽然得到了私密性,但是访问不了js文件中的东西 -->
    </head>
    <body>
        <div></div>
        <script type="module">
            import obj1 from "./1.js"
            import obj2 from "./2.js"
            import obj3 from "./3.js"
            obj1.test();
            obj2.test(); 
        </script>
    </body>
    </html>
    
  • 导入导出写法一

    export default A1
    
    import a1 from "./1.js"
    
  • 导入导出写法二

    export {A1,A2}
    
    import {A1,A2} from "./1.js"
    
    import {A1 as a1,A2 as a2} from "./1.js"
    
    import * as obj from "./1.js"
    
  • 导入导出写法三

    export function A1(){
        console.log("A1");
    }
    export function A2(){
        console.log("A2");
    }
    
    import {A1,A2} from "./1.js"
    
    import {A1 as a1,A2 as a2} from "./1.js"
    
    import * as obj from "./1.js"
    
  • 混合写法

    export {A1}
    export default A2
    
    import A2,{A1} from "./1.js"
    

4.ES7:新特性

  • 求幂运算符

    Math.pow(3,2) === 3 ** 2 //9
    
  • 数组的includes方法

    [1, 2, NaN].includes(NaN)    // true
    [1, 2, NaN].indexof(NaN)    // -1
    

5.ES8:async和await

  • Async

    • 使得异步操作变得更加方便
      • 更好的语义
      • 返回值为 Promise
    async function test(){
        console.log("test");
        // return "success-111";
        return new Promise((resolve,reject) => {
            resolve("data-111");
            // reject("err-222");
        })
    }
    let res = test();
    res.then(res => {
        console.log("success",res);
    }).catch(err => {
        console.log("err",err)
    })
    

image-20230810205021411.png

async 返回时是非 Promise 对象,则状态为 fulfiled,then指定

async 返回的是 Promise 对象,则状态由该 Promise 对象决定

  • Await

    • await 命令后面是一个 Promise 对象,返回该对象的结果,如果不是 Promise就直接返回对应值
    function ajax(){
        return new Promise((resolve,reject) => {
            setTimeout(() => {
                console.log("ajax-成功");
                resolve("data-111");
            },1000)
        })
    }
    
    async function test(){
        let res = await ajax();
        console.log(res);
    }
    test()
    
  • 结合手动封装的ajax

    function ajax(url){
        return new Promise((resolve,reject) => {
            let xhr = new XMLHttpRequest();
            xhr.open("get",url,true);
            xhr.send();
            xhr.onreadystatechange = function(){
                if(xhr.status >= 200 && xhr.status < 300){
                    resolve(JSON.parse(xhr.responseText));
                }else{
                    reject(xhr.responseText);
                }
            }
        })
    }
    
    async function test(){
        let res = await ajax("1.json"); 
        console.log(res); // data-111
        let res1 = await ajax("2.json",res);
        console.log(res1); // data-222
    }
    test()
    
  • 错误处理

    try{
        let res1 = await ajax("http://localhost:8080...");
        let res2 = await ajax("http://localhost:8080...");
    }catch(err){
        console.log("err",err)
    }
    

    可以接收test()方法放回置的Promise对象进行 then 和 catch来执行相应逻辑代码,也可以在test()函数内进行try catch 来捕获执行相应逻辑代码

6.ES8:对象方法扩展、克隆对象

  • Object.values(obj):获取对象的所有value值

    let obj = {
        name: "haonan",
        age: 22
    }
    console.log(Object.values(obj)); // ['haonan',100]
    
  • Object.entries(obj):获取对象所有的属性名和属性值

    let obj = {
        name: "haonan",
        age: 22
    }
    console.log(Object.entries(obj));
    

image-20230810205032444.png

  • Object.getOwnPropertyDescriptors(obj):获取对象的所有详细信息

    let obj = {
        name: "haonan",
        age: 22
    }
    console.log(Object.getOwnPropertyDescriptors(obj));
    

image-20230810205039351.png

  • 克隆对象

    let obj1 = {
        name: "haonan",
        age: 100,
        location:{
            province: "河南",
            city: "洛阳",
        },
        // 只设置city
        get city(){
            return this.location.city
        }
        set city(value){
            this.location.city = value
        }
        get upperName(){
            return this.name
        }
        set upperName(value){
            this.name = value.substring(0,1).toUpperCase() + value.substring(1)
        }
    }
    let obj2 = {};
    
    // Object.aasin(obj2,obj1); 无法克隆 get set方法
    Object.defineProperties(obj2,Object.getOwnPropertiyDescriptors(obj1));
    

assign 无法克隆到对象的get set 方法,导致克隆遗漏,Object.getOwnPropertyDescriptors(obj)则不会

7.ES8:字符串填充、函数参数末尾加逗号

  • padStart()、padEnd()方法可以使得字符串达到固定长度,有两个参数,字符串目标长度和填充内容

    let str = "haonan";
    
    console.log(str.padStart(10,"x")); // xxxxhaonan
    console.log(str.padEnd(10,"x")); // haonanxxxx
    console.log(str.padStart(5,"x")); // haonan
    console.log(str.padEnd(5,"x")); // haonan
    
    • 使用场景:时间小于10补0的状态
    let time = [];
    for(let i = 0;i<13;i++){
        time.push((i+"").padStart(2,"0"));
    }
    
  • 函数参数的末尾加逗号

    在添加新的参数、属性、元素时有用,可以直接新加一行而不必给上一行再补充一个逗号,这样使版本控制工具的修改记录更加整洁【例如Git】

    function test(
        a,
        b,
        c,
    ){
        console.log(a,b)
    }
    

8.ES9:对象的剩余参数与扩展运算符

  • 对象的剩余参数

    let obj = {
        name: "haonan",
        age: 22,
        location: "洛阳"
    }
    let {name,...other} = obj
    console.log(name); // haonan
    console.log(other); // {age: 22,location:'洛阳'}
    
  • 对象的扩展运算符:浅复制对象

    let obj1 = {
        name: "mahaonan",
        location: "洛阳"
    }
    let obj2 = {
        name: "haonan",
        age: 22
    }
    // Object.assign
    let obj3 = {...obj1,...obj2};
    console.log(obj3);
    

image-20230810205055006.png

  • 正则表达式命名捕获组

    ES9后允许使用命名捕获,在打开捕获符号后立即命名

    let str = "今天是2022-10-10";
    let reg = /(?<year>0-9{4})-(?<month>0-9{2})-(?<day>0-9{2})/g;
    
    let res1 = reg.exec(str)
    console.log(res1);
    

image-20230810205101544.png

9.ES9:Promise.finally()

无论是成功还是失败,都会运行的代码,比如隐藏对话框,关闭数据库连接等

function ajax(){
    return new Promise((resolve,reject) => {
        resolve(111);
    })
}
// showLoading
ajax().then(res => {

}).catch(err => {

}).finally(() => {
    // hideloading
})

10.ES9:异步遍历器

  • 同步遍历器问题

    function *fn(){
        yield 111
        yield 222
    }
    let syncI = fn();
    console.log(syncI.next());
    console.log(syncI.next());
    console.log(syncI.next());
    

image-20230810205111098.png

  function *fn(){
      yield new Promise(resolve => resolve("111"));
      yield new Promise(resolve => resolve("222"));
  }
  let syncI = fn();
  syncI.next().value.then(res => console.log(res));
  syncI.next().value.then(res => console.log(res));

image-20230810205116170.png

value 属性的返回值是一个 Promise 对象,用来放置异步操作,但是这样编写较为麻烦,不符合直接,语义也比较绕

  • 异步遍历器生成函数

    • Generator 函数返回的是一个同步遍历器,异步 Generator 函数的作用,是返回一个异步遍历器对象。异步 Generator 函数就是 async 函数与 Generator 函数的结合
    async function *fn(){
        yield new Promise(resolve => resolve("111"));
        yield new Promise(resolve => resolve("222"));
    }
    let gen = fn();
    gen.next().then(res => {
        console.log(res);
        return gen.next();
    }).then(res => {
        console.log(res);
        return gen.next();
    }).then(res => {
        console.log(res);
    })
    

image-20230810205123552.png

  • for await of

    for...of 循环用于遍历同步的 Iterator 接口,而改循环是用于遍历异步的 Iterator 接口

    asnyc function test(){
        for await(let i of gen){
            console.log(i);
        }
    }
    
  • 案例

    function timer(t){
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(t);
            },t)
        })
    }
    async function *gen(){
        yield timer(1000);
        yield timer(2000);
        yield timer(3000);
    }
    async function test(){
        for await(let i of gen()){
            console.log(i)
        }
    }
    test()
    

results matching ""

    No results matching ""