【菜狗学前端】ES6+笔记(包含Promise及async、await等)

老样子。复制上来的图片都没了,想看原版可以移步对应资源下载(资源刚上传,还在审核中)

(免费)菜狗学前端之ES6+笔记icon-default.png?t=N7T8https://download.csdn.net/download/m0_58355897/89135424

一 解构赋值

        解构赋值

        解构指的是把一个数据结构拆开

        赋值则是把其赋值给另外一个一摸一样的数据结构

        三类

        1.数组的解构赋值

        2.对象的解构赋值

        3.字符串的解构赋值

(一) 数组的解构赋值

数组解构的核心是 结构保持一致

var names = ['小强', '张三', '李四']

var [name1, name2, name3] = names

PS:不完全解构

let arr2 = [1, 2]
let [num1] = arr2

HTML
    <script>
        // 数组解构的核心是 结构保持一致

        var names = ['小强', '张三', '李四']

        // 需求:想让这里面的名字拿出来 分别命名为name1 name2 name3
        // 之前写法:var name1=names[0]

        // 可以使用解构赋值来实现 注意保持结构一模一样
        var [name1, name2, name3] = names
        console.log(name1);//小强
        console.log(name2);//张三
        console.log(name3);//李四
    </script>

    <script>
        var arr1 = [
            {userName: '旺财', age: 18 },
            [99, 88],
            111
        ]

        // 需求:把数据拿出来 userName age  score  id
        var [{ userName, age }, score, id] = arr1
        console.log(userName);//旺财
        console.log(age);//18
        console.log(score);//[99, 88]
        console.log(id);//111
    </script>

    <script>
        let arr2 = [1, 2]
        // 不完全解构(即不完全拿到数据)
        let [num1] = arr2
        console.log(num1);//1

        let arr3 = [1]
        let [num2, num3] = arr3
        console.log(num2);//1
        console.log(num3);//und
    </script>

(二) 对象的解构赋值

对象解构的核心是 属性名保持一致

        let obj = { username: '旺财', age: 18 }

当对象的属性名和属性值一样时 可以省略为一个

        let { username: username, age: age } = obj

        let { username, age } = obj

PS:

当对象解构赋值时,不能修改里面的value值

但是可以在解构赋值的过程中新添加一个值

let obj2 = { username1: '旺财', age1: 18, sex1: '女' };

let { username1, age1, sex1 = '男' } = obj2

HTML
     <script>
        let obj3 = {
            arr: [
                'hello',
                { msg: 'es6' }
            ]
        }

        let {
            arr: [
                str1,
                { msg: str2 }
            ]
        } = obj3;
        console.log(str1, str2);//hello es6
    </script>
    <script>
        let obj4 = {
            f1: function () {
                console.log(1);
            },
            f2: function () {
                console.log(2);
            }
        }

        // 对象的不完全解构

        let { f1 } = obj4;
        f1()// 1
        f2()// f2 is not defined
    </script>

(三) 字符串的解构赋值

字符串的解构赋值 某种意义上 可以参照数组

        var str = 'h e'

        // 左边是[]罩起来不是''

        let [a, b, c] = str

        console.log(a);//h

        console.log(f);//

        console.log(g);//E

(四) 函数形参的解构赋值

JavaScript
        function bar([x, y]) {
            console.log(x);
            console.log(y);
        }
        // [x, y]=[1, 2]
        bar([1, 2])

        function fn({ x, y, z = 3 }) {
            console.log(x);
            console.log(y);
            console.log(z);
        }
        // { x, y, z = 3 }={ x: 1, y: 2}
        fn({ x: 1, y: 2 })

二 展开运算符和rest运算符

(一) 展开运算符

        展开运算符 又叫 拓展运算符        形式:...

        可以把一个数组转换为用逗号分开的序列

JavaScript
        // 需求: 将两个数组进行合并
        var arr1 = [1, 2, 3]
        var arr2 = [4, 5, 6]
        var arr3 = [...arr1, ...arr2]
        console.log(arr3);//[1, 2, 3, 4, 5, 6]
        // 需求:找最大值
        var arr4 = [2, 4, 6, 57, 3, 2, 6, 78, 54, 3, 2];  
        console.log(Math.max(...arr4));//78

(二) rest运算符

rest运算符 形式:...

JavaScript
        // 当前你要定义一个函数 但是这个函数的参数不确定
        function fn(...args) {
            console.log(args);
        }
        fn([1, 2], 3)
        
        // 解构赋值+res运算符... 只能获取前几个值
        var arr1 = [1, 2, 3, 4]
        //A rest element must be last in a destructuring pattern
        // let [a, ...b, c] = arr1
        let [a, b, ...c] = arr1
        console.log(a);//1
        console.log(b);//2
        console.log(...c);//3 4
        console.log(c);//[3 4]

(三)展开和rest运算符区别

当...出现在赋值运算符右侧/作为函数实参时:拓展(展开)运算符

    var arr3 = [...arr1, ...arr2]

    Math.max(...arr4)

当...出现在赋值运算符左侧/作为函数形参时:rest运算符

    let [a, b, ...c] = arr1

    function fn(...args) {

                console.log(args);

            }

PS: args-- arguments 参数

三 浅拷贝对象Object.assign()

        Object.assign() --浅拷贝

        浅拷贝--拷贝了地址,共用一个堆空间,所以一个改变其他随之改变

        作用:将源对象的所有可枚举的属性 复制到目标对象

        需要2个参数

        第一个参数是目标参数 -- obj3

        后续的参数都是源对象 -- obj1,obj2

PS:

Object.assign VS cloneNode

浅克隆-cloneNode()  仅克隆该节点,不克隆其中后代节点

深克隆-cloneNode(true)  将节点的后代节点也克隆

JavaScript
        var obj1 = {
            name: 'zhangsan',
            address: '郑州',
            hobby: '写代码'
        }
        var obj2 = {
            age: 18
        }
        Object.assign(obj3, obj1, obj2)
        console.log(obj3);
        
        // Object.assign -- 浅拷贝
        // 深拷贝(开辟了一个新的堆地址,各自独立拥有堆空间)
        // 浅拷贝(拷贝了地址,共用一个堆空间)
        var obj7 = {
            address: {
                city: "郑州"
            }
        }
        var obj8 = {}
        Object.assign(obj8, obj7)
        // 改的是obj8属性但是obj7随之改变--因为浅拷贝,指向同一地址
        obj8.address.city = "上海"
        console.log(obj7);//上海

四 Object.defineProperty()

(一) 给对象添加属性并添加对应配置项

JavaScript
            var obj = {}
            //
            Object.defineProperty(obj, 'age', {
                value: 18,
                // 是否可被枚举
                enumerable: false //默认值是false  不可被枚举
            })
            console.log(obj);
    
    
            // 不可被枚举  for in也循环不到
            for (let key in obj) {
                console.log(obj[key]);
            }
    
            // 不可被枚举  不能被复制
            let obj6 = {}
            Object.assign(obj6, obj)
            console.log(obj6);

(二) 监听对象的多个属性 循环遍历

JavaScript
        let obj1 = {
            name: '张三',
            age: 18,
            money: 5000
        }
        for (let key in obj1) {
            Object.defineProperty(obj1, key, {
                set(value) {
                    // value -- 被修改的新值
                    console.log('set被调用了');
                    console.log('set的新值:' + value);
                },
                get() {
                    console.log('get被调用了');
                }
            })
        }
        console.log(obj1.name);//get被调用了
        obj1.money = 3000;//set被调用了 set的新值:3000

五 Proxy代理

proxy --代理

代理模式 --程序设计的一种设计模式     监听一个对象上的属性

Proxy用于修改某些操作的默认行为, 可以理解在目标对象之前,设置了一个拦截 ,如果外界去访问对象(数据)的时候,都需要通过这层拦截,就可以对外界的访问进行过滤和改写

(一) Proxy代理相关概念

1.Proxy作用

        1.屏蔽原始数据      2.保障原始数据安全

2.Proxy构造器中参数

        第一个参数 代理对象    第二个参数 配置项

(二) Proxy捕获器

JavaScript
        let obj = {
            name: '李四',
            age: 18
        }
        let objProxy = new Proxy(obj, {
            // 监听获取动作
            get: function (target, key) {
                console.log('get被执行了');

            },
            // 监听设置动作
            set: function (target, key, newValue) {
                console.log('set被执行了');
                console.log(newValue);
            },
            // 监听in动作
            has: function (target, key) {
                console.log('in捕获器');
                return key in target
            },
            // 监听删除动作
            deleteProperty: function (target, key) {
                console.log('delete触发了');
            }
        })

        // in 判断属性有没有在这个对象上 或者说 对象上有没有此属性
        console.log('name' in objProxy);//true        delete objProxy.name//不影响obj
        console.log(obj);

六 class

(一)class概念及使用

class是一个语法糖,就是你相同代码的功能可以简写

箭头函数也是语法糖

JavaScript
        class Student {
            // 如果想要给这个类的对象添加属性的时候
            constructor(name, age) {
                // 挂载在对象身上的私有属性
                this.name = name
                this.age = age
                // constructor的作用
                // 1.创建一个对象
                // 2.将Person的prototype赋值给创建出来的实例化对象 p.__proto__=Person.prototype
                // 3.让this指向对象p--让this指向p
                // 4.执行内部代码
            }
            // 挂载在原型对象上 公有属性
            say() {
                console.log('say...');
            }
        }
        // class继承extends
        class Mointor extends Student {
            constructor(name, age, id) {
                super(name, age)
                this.id = id
            }
        }
        let m = new Mointor("张三", 18, 1)
        console.log(m);

(二)class设置器和访问器

JavaScript
        class Student {
            constructor(address, age) {
                this._address = address
                this.age = age
            }
            // 访问器
            get address() {
                console.log('get被调用了');
                return this._address
            }
            // 设置器
            set address(value) {
                console.log('set被调用了');
                this._address = value
                // console.log('设置值:' + value);
            }
        }

        let stu = new Student('郑州', 18)
        console.log(stu._address);//加上下划线相当于正常的访问属性
        console.log(stu.address);//不加下划线 相当于通过get set去访问的

        // stu._address = '上海'
        stu.address = '上海';
        console.log(stu);

(三)class静态属性|方法 static

静态属性|方法 static

  • 如果在一个方法前,加上static关键字,就表示该方法不会被实例继承
  • 只能通过构造器去访问 不能通过实例之后的对象来访问

且静态方法里的this只能访问静态属性

HTML
   <script>
        class Person {
            // 静态属性/方法
            static say() {
                console.log(11);
            }
        }
        // 静态属性 只能通过构造器去访问 不能通过实例之后的对象来访问
        Person.say()
        // 注意:不能通过实例之后的对象变量来访问
        let p = new Person()
        p.say() //say is not a function
    </script>
    
    <script>
        // 静态方法里的this只能访问静态属性
        class Person {
            // 公共属性
            static names = "张三"//静态属性
            age = 18
            static show() {
                console.log(this.names);//张三
                console.log(this.age);//und
                console.log(Person === this);//true
            }
        }
        Person.show()//张三 und

七 Symbol()

问题:协同开发 对象中属性名冲突

问题本质原因:属性名的不唯一性

解决方法:Symbol()

属性名可重复 只是书写方式不同:属性名需加[]

let mySymbol1 = Symbol('mySymbol1')

mySymbol1: 'mySymbol1',
[mySymbol1]: '第一种方式'

调用方式不同:一个对象打点,一个对象[]
console.log(obj.mySymbol1);
console.log(obj[mySymbol1]);

(一) Symbol()特点

  • 这种数据由Symbol函数产生 独一无二
  • 可保证对象中属性名是唯一的
  • 可传递字符串作为参数

JavaScript
        let s3 = Symbol('s')
        let s4 = Symbol('s')
        console.log(s3);//Symbol(s)
        console.log(s3 == s4);//false

(二) 通过Symbol()避免属性名冲突-三种方式

JavaScript
        let obj = {}
        // 第一种方式[mySymbol1]: '第一种方式'
        let mySymbol1 = Symbol('mySymbol1')
        obj = {
            mySymbol1: 'mySymbol1',
            [mySymbol1]: '第一种方式'
        }
        // 这样属性名就可重复,只是调用方式不同
        console.log(obj.mySymbol1);
        console.log(obj[mySymbol1]);

        // 第二种方式 obj[mySymbol2] = '第二种方式';
        let mySymbol2 = Symbol('mySymbol2')
        obj[mySymbol2] = '第二种方式';
        console.log(obj[mySymbol2]);

        // 第三种方式 Object.defineProperty()
        let mySymbol3 = Symbol('mySymbol3')
        Object.defineProperty(obj, mySymbol3, {
            value: '第三种方式',
            enumerable:true
        })
        console.log(obj[mySymbol3]);

        console.log(obj);

八 Set和Map

        Es6中 新增了两种结构 set map weakset weakmap

        应用场景:

        Map:适用于需要将键映射到值的情况,例如管理用户权限、存储对象之间的关联关系等

        Set:适用于需要存储一组唯一值的情况,例如去重数组中的重复项、跟踪一组唯一的项目等

        set和数组结构相似 但是set可以去重,set里没有重复的元素

(一) Set

1.Set操作方法

1.add(value) 返回Set结构本身

2.delete(value) 返回布尔值-删除是否成功

3.clear() 清除所有成员 返回值undefined

4.has(value) 返回布尔值-参数否是Set的成员

PS:Set实例化对象添加重复元素无效

JavaScript
        let s = new Set()
        s.add(1)
        s.add(1)//添加重复元素无效
        console.log(s.add(2));//Set(2) {1, 2}
        console.log(s.has(2));//true
        console.log(s.delete(2));//true
        s.clear();
        console.log(s);//Set(0) {size: 0}

2.Set转Array--Array.from()

JavaScript
        let s = new Set()
        s.add(1)
        s.add(2)
        s.add(3)
        console.log(s);
        //通过Array.from()方法将Set转为Array
        let arr = Array.from(s)
        console.log(arr);

3.WeakSet-成员类型只能是对象类型

WeakSet 和Set类似的另一个数据结构 也是内部成员不能重复

1.WeakSet成员类型只能是对象类型 不能放其他类型

2.WeakSet不能遍历 如果遍历了 获取其中的元素 那么里面的对象无法被正常销毁

JavaScript
        let weakset = new WeakSet()
        let obj1 = {
            name: '1'
        }
        let obj2 = {
            name: '2'
        }
        weakset.add(obj1)
        weakset.add(obj2)
        // weakset.add(1)//Invalid value used in weak set
        console.log(weakset);

(二) Map

1.Map操作方法

 set(key,value)

 get(key)

 has(key)

 delete(key)

 clear()

JavaScript
        let map = new Map()
        let obj = {
            city: "郑州"
        }
        map.set(obj, '大玉米')
        console.log(map.set('开封', '清明上河园'));//Map(2) {{…} => '大玉米', '开封' => '清明上河园'}
        console.log(map.has(obj));//true
        console.log(map.get(obj));//大玉米
        console.log(map.delete(obj));//true
        console.log(map); //Map(1) {'开封' => '清明上河园'}

2.WeakMap-用key只能是对象类型

1.WeakMap 用对象作为key 不能使用基本数据类型作为key

2.WeakMap不能遍历

九 Promise

 (一) 前置知识--JS代码执行顺序

js代码执行顺序:同步代码-->异步代码(微任务->宏任务)

异步任务 宏任务和微任务 特点:先微后宏

  1. 同步任务
  •  按照顺序执行,执行完一个再执行下一个
  1. 异步任务(宏任务和微任务)
  1. 微任务:Promise.then、Promise、async/await
  1. 宏任务:定时器(setTimeout setInterval)、事件监听、Ajax、DOM事件
  • 在后台执行,等到异步任务完成后再执行回调结果。
  • 异步任务执行顺序不确定,因为在后台执行

PS:

1.async内遇到await先执行await,其中有异步代码的话--阻塞async后面代码执行,但不阻塞async外代码继续执行

2.promise执行resolve()或者reject()改变状态时才会把其then方法放进微任务队列

3.Event Loop

 (二) 旧解决异步问题方式-回调函数

异步问题:js单线程执行,如何实现异步

之前的方式:回调函数

缺点:过多函数嵌套导致出现”回调地狱”

JavaScript
    // 最早解决异步问题:靠回调函数
    // 1.设计这样的一个函数
    function execCode(counter, successCallback, failureCallback) {
        // 异步任务
        setTimeout(() => {
            if (counter > 0) { // counter可以计算的情况
                let total = 0
                for (let i = 0; i < counter; i++) {
                    total += i
                }
                // 在某一个时刻只需要回调传入的函数
                successCallback(total)
            } else { // 失败情况, counter有问题
                failureCallback(`${counter}值有问题`)
            }
        }, 3000)
    }
    // 2.ES5之前,处理异步的代码都是这样封装
    execCode(100, (value) => {
        console.log("本次执行成功了:", value)
    }, (err) => {
        console.log("本次执行失败了:", err)
    });

(三) Promise相关概念

1.promise概念及作用

概念:promise是解决异步编程的一种解决方案,合理且强大 可以替代传统的解决方案-回调函数

好处:异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数

作用:主要是为了解决异步的问题 让异步代码先执行

PS:promise可以解决异步的问题,但不能说promise本身是异步的

2.Promise对象特点

  • 对象的状态不受外界影响
  • 一旦状态改变不会二次更改

3.Promise对象的三种状态--PromiseState属性

  1. 等待状态:pending 默认创建出来promise出于等待状态
  1. 成功状态:fulfilled 当调用resolve函数时,promise从等待态变为成功态
  1. 失败状态:rejected 当调用reject函数时,promise从等待态变为失败态

PS:

对一个Promise对象来说 成功或失败后 不能再次改变其状态

即只能从等待状态转为成功状态 / 从等待状态转为失败状态

JavaScript
        // 1.等待态 pending 默认
        let p1 = new Promise((resolve, reject) => {

        })
        console.log(p1);

        // 2.成功态 fulfilled 调用resolve()
        let p2 = new Promise((resolve, reject) => {
            resolve('resolve')
        })
        console.log(p2);

        // 3.失败态 rejected 调用reject()
        let p3 = new Promise((resolve, reject) => {
            reject('reject')
        })
        console.log(p2);

        // 注意事项:
        // 对一个Promise对象来说 成功或失败后 不能再次改变其状态
        // 即只能从等待状态转为成功状态 / 从等待状态转为失败状态
        let p4 = new Promise((resolve, reject) => {
            resolve('resolve')
            reject('reject')//无效
        })
        console.log(p4);//状态仍为fulfilled成功状态

4.Promise对象的三种终值--PromiseResult属性

  1. pending --终值 undefined
  1. fulfilled --终值 成功的结果
  1. rejected --终值 失败的原因

(四) Promise的then方法

1.每个promise对象都有then方法

  • then的作用:then可以处理promise对象成功或失败之后的事情
  • then的2个参数:分别对应成功后的回调和失败后的回调

JavaScript
    let p1 = new Promise((resolve, reject) => {
        resolve('成功')
    })
    // 传递一个参数--指的是成功的结果 PromiseResult
    p1.then((result) => {
        console.log(result);
    })

    let p2 = new Promise((resolve, reject) => {
        reject('失败')
    })
    // 传递两个参数--一成功的结果 一失败的结果 PromiseResult
    p2.then((result) => {
        console.log(result);
    }, (error) => {
        console.log(error);
    })

2.then的返回值

then的返回值是一个新的promise对象

  1. 返回成功态的promsie:上一个then返回一个普通的值(包含und)
  1. 返回失败态的promise对象:上一块代码报错
  1. 返回新的promise对象:then的返回值是一个新的promise对象
  1. 返回成功态的promsie:上一个then返回一个普通的值(包含und)

JavaScript
        let p1 = new Promise((resolve, reject) => {
            // reject('失败')
            resolve('成功')
        })
        // 上一个then返回一个普通的值(包含und) 新的promise是成功的promsie
        let p2 = p1.then((result) => {
            console.log(result);//成功
        }, (error) => {
            console.log(error);
        })
        console.log(p1);
        console.log(p2);

  1. 返回失败态的promise对象:上一块代码报错

JavaScript
        let p1 = new Promise((resolve, reject) => {
            // reject('失败')
            resolve('成功')
        })
        let p2 = p1.then((result) => {
            console.log(result);//成功
            throw new Error('出了小错')
        }, (error) => {
            console.log(error);//失败
            throw new Error('出了小错')
        })
        console.log(p1);
        console.log(p2);

  1. 返回新的promise对象:then的返回值是一个新的promise对象

JavaScript
        let a = new Promise((resolve, reject) => {
            resolve('成功')
            // reject('失败')
        })
        let a1 = a.then(result => {
            // 在成功态里面返回了一个失败态的promise
            console.log(result);
            let a3 = new Promise((resolve, reject) => {
                reject('失败')
            })
            return a3
        }, error => {
            console.log(error);
            // 在失败态里面返回了一个成功态的promise
            let a4 = new Promise((resolve, reject) => {
                resolve('成功')
            })
            return a4
        })
        console.log(a1);

3.then的顺延

  • 1.1少写一个参数
  • 1.2不写参数
  • catch会把then失败的情况单独拎出来
  • finally -- 最终都会走这个finally
  1. 少写一个|不写参数

JavaScript

        // 当你promise对象的then中没有成功或者失败的处理 那么会顺延到下一个promise对象中做处理

        let p2 = new Promise((resolve, reject) => {
            reject('失败')
        })
        p2.then(result => {
            console.log(1);
        }).then(result => {
            console.log(3);
        }, errer => {
            console.log(4);
        })

        // 1.2不写参数
        let p3 = new Promise((resolve, reject) => {
            resolve('成功')
        })
        p3.then().then(result => {
            console.log(3);
        }, error => {
            console.log(4);
        })

  1. catch 把then失败的情况单独拎出来

JavaScript
        let p4 = new Promise((resolve, reject) => {
            reject('失败')
        })
        p4.then(result => {
            console.log('处理成功');
        }).catch(error => {
            console.log('处理失败');
        })

  1. finally 最终都会走这个finally

JavaScript
        let p5 = new Promise((resolve, reject) => {
            reject('失败')
        })
        p5.then(result => {
            console.log('处理成功');
        }).catch(error => {
            console.log('处理失败');
        }).then(result => {
            // 前面return的值,result拿到的是上一个promise的终值
            console.log(result);//und
        }).finally(() => {
            console.log('最终');
        })

(五) 利用Promise解决异步问题

JavaScript
        function fn(num) {
            // 同步代码
            return new Promise((resolve, reject) => {
                setTimeout(function () {
                    console.log('异步1');
                    if (num >= 50) {
                        resolve('v我50')
                    } else {
                        reject('v你50')
                    }
                }, 1000)
                console.log('同步1');
            })
        }

        // .then函数内 异步代码
        fn(49).then((result) => {
            console.log(result);
        }, (error) => {
            console.log('异步2');
            console.log(error);
        })//v你50

        console.log('同步2');
        
        //同步1 同步2 异步1 异步2 v你50

(六) Promise的resolve的实参

1.普通参数

JavaScript
resolve('成功')

2.参数是一promise对象

JavaScript
            let p2 = new Promise((resolve, reject) => {
                reject('失败1')
            })
            resolve(p2)

3.是一个thenable (一不完整的promise对象)

thenable:就是一个对象中有一个then函数

JavaScript
            resolve({
                //then: function(resolve, reject) {}
                then(resolve, reject) {
                    reject('失败2')
                }
            })

(七) Promise的静态方法

1、2. resolve、reject

JavaScript
        // 最常规的两个静态方法  1.resolve  2.reject
        // 可以直接创建一个成功或者失败的promise对象
        let p1 = Promise.resolve('成功')
        console.log(p1);

        let p2 = Promise.reject('失败')
        console.log(p2);

3.all

JavaScript
        // 3.all
        // 表示所有的promise都成功后 得到所有promise成功的结果
        // 如果有一个失败 则直接得到最先失败的promise的结果
        // all参数传递的是一个数组的格式

        let p3 = new Promise((resolve, reject) => {
            setTimeout(() => {
                // resolve('p3成功')
                reject('p3失败')
            }, 3000)
        })
        let p4 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('p4成功')
            }, 2000)
        })
        let p5 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('p5成功')
            }, 4000)
        })
        Promise.all([p3, p4, p5]).then(result => {
            console.log(result);
        }).catch(error => {
            console.log('走了catch');
            console.log(error);
        })
        //['p3成功', 'p4成功', 'p5成功']

4.any

JavaScript
        // 4.any
        // 等待最先成功的promise 或者 得到所有Promise都失败(All promises were rejected)

        let p3 = new Promise((resolve, reject) => {
            setTimeout(() => {
                // resolve('p3成功')
                reject('p3失败')
            }, 3000)
        })
        let p4 = new Promise((resolve, reject) => {
            setTimeout(() => {
                // resolve('p4成功')
                reject('p4失败')
            }, 2000)
        })
        let p5 = new Promise((resolve, reject) => {
            setTimeout(() => {
                // resolve('p5成功')
                reject('p5失败')
            }, 4000)
        })
        Promise.any([p4, p5, p3]).then(result => {
            console.log('走了then');
            console.log(result);
        }).catch(error => {
            console.log('走了catch');
            console.log(error);//All promises were rejected
        })

5.allSettled

JavaScript
        // 5. allSettled
        // 表示所有的promise的结果 不管成功还是失败 最后都会走成功态方法result=>{}
        let p3 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('p3成功')
            }, 3000)
        })
        let p4 = new Promise((resolve, reject) => {
            setTimeout(() => {
                // resolve('p4成功')
                reject('p3失败')
            }, 2000)
        })
        let p5 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('p5成功')
            }, 4000)
        })
        Promise.allSettled([p4, p5, p3]).then(result => {
            console.log('走了then');
            console.log(result);
        }).catch(error => {
            console.log('走了catch');
            console.log(error);
        })

6.race

JavaScript
        //  6. race
        //  等待最先拿到状态的promise结果 不管成功还是失败
        let p3 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('p3成功')
                // reject('p3失败')
            }, 3000)
        })
        let p4 = new Promise((resolve, reject) => {
            setTimeout(() => {
                // resolve('p4成功')
                reject('p4失败')
            }, 2000)
        })
        let p5 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('p5成功')
            }, 4000)
        })
        Promise.race([p5, p4, p3]).then(result => {
            console.log('走了then');
            console.log(result);
        }).catch(error => {
            console.log('走了catch');
            console.log(error);

        })

十 async+await(≈Promise)

  • async关键字(修饰符) 是异步的简写 用于声明一个异步函数
  • async用于声明一个function是异步的
  • 函数用async修饰后,变成异步函数,会返回一个promise对象
  • await关键字 async wait的简写
  • await 不能单独使用,必须在async的修饰下使用
  • await 用于等待一个异步方法执行完成

个人理解:

  • async与new Promise()功能类似
  • 返回promise对象,不加await正常执行
  • await与promise.then()方法类似
  •  async内遇到await时,若await的函数中有异步代码则不再向下执行-async内部阻塞,但是async外面的同步代码仍正常运行

(一) async

1.async的几种写法

具名函数、匿名函数、箭头函数、使用class声明类

JavaScript
        // 具名函数的写法
        async function fn() {
            console.log(123);
        }
        console.log(fn());

        // 匿名函数的写法
        let gn = async function () {

        }
        console.log(gn());

        // 箭头函数的写法
        let tn = async () => { }
        console.log(tn());

        // 使用class声明类
        class Person {
            async eat() {

            }
        }
        let p = new Person()
        console.log(p.eat());

2.async函数return返回值-对应promise状态

  1. 返回是一个普通值/不返回(即und) 那么整个promise状态是成功态
  2. 返回的是一个promise对象 内部的promise对象的最终状态会影响到外部
  3. 返回的是一个thenable对象 内部的thenable对象的最终状态会影响到外部

            return {

                then(resolve, reject) {

                    reject('失败')

                }

            }

  1.   4.代码中有异常,抛出错误(代码运行并不终止) 那么整个promise就是一个失败态

JavaScript
        async function foo() {
            // 1.返回是一个普通值 状态是成功态
            return 123

            // 2.返回的是一个promise对象 内部的promise对象的最终状态会影响到外部
            // return new Promise((resolve, reject) => {
            //     // resolve('成功')
            //     reject('失败')
            // })

            // 3.返回的是一个thenable对象 内部的thenable对象的最终状态会影响到外部
            // return {
            //     then(resolve, reject) {
            //         reject('失败')
            //     }
            // }

            // 4.代码中有异常,抛出错误,那么整个promise就是一个失败态
            // console.log(a);
        }
        console.log(foo());
        foo().then(result => {
            console.log(result);
        }, err => {
            console.log(err);
        })
        console.log('hhhh');

        // Promise
        // hhhh
        // 123

(二) await

await 不能单独使用,必须在async的修饰下使用

PS:

  1. await等待的是一个成功的promise的结果,拿到成功的结果,才会执行async内的后续代码否则中断不再执行
  1. await执行过程中遇到异步代码会阻塞不再向下执行async内部代码,但同时不影响async外部剩下同步代码的执行

JavaScript
        // await等待的是一个成功的promise的结果,拿到成功的结果,才会执行async内的后续代码
        // async+await可替换new Promise()+then
        async function foo() {
            await new Promise((resolve, reject) => {
                // resolve('成功')
                reject('失败')//微任务
                console.log(1);
            })
            console.log(111);//未执行
        }
        foo()//1
        console.log('async外的同步代码');//async外的同步代码

十一 ES6+中的其他方法

(一) Object.keys和Object.values和Object.entries

        通过 Object.keys 获取一个对象所有的key

        通过 Object.values 来获取所有的value值

        通过 Object.entries -- 对对象、数组/字符串的操作

        对对象:获取所有的[key,value]值

        对数组/字符串:获取所有的索引+数组/字符串对应项

JavaScript
        let obj = {
            name: 'wc',
            age: 18,
            height: 180,
            address: 'zz'
        }
        console.log(Object.keys(obj));
        console.log(Object.values(obj));
        console.log(Object.entries(obj));
        console.log(Object.entries(['zs', 'ls']));
        console.log(Object.entries("hi"));

(二) String的padStart()|padStart()

String Padding 某些字符串进行前后的填充,来实现某种格式化效果

应用场景:比如需要对身份证、银行卡的前面位数进行隐藏

  • padStart() 用于头部补全
  • padEnd() 用于尾部补全

JavaScript
        let cardNumber = '410233043254032403';
        // 截取前14位
        let sliceNumber = cardNumber.slice(0, 14)
        // 总长度cardNumber.length,减去sliceNumber.length剩余位数用'*'替换
        cardNumber = sliceNumber.padEnd(cardNumber.length, '*')
        console.log(cardNumber);//41023304325403****

(三)flat() 按指定的深度递归遍历数组

JavaScript
        // 三维数组
        let nums = [
            10, 20, [111, 222], [333, 444], [[123, 321, ["a", "b"]], [456, 654]]
        ]
        // flat(0)深度为0
        let numarr = nums.flat(0)
        console.log(numarr);
        // nums.flat()与nums.flat(1)都是深度为1
        numarr = nums.flat(1)
        console.log(numarr);
        numarr = nums.flat(2)
        console.log(numarr);
        //深度Infinity-无穷大
        numarr = nums.flat(Infinity)
        console.log(numarr);

(四)||和??

  1. ||  逻辑或运算符
  • 如果第一操作值为假值(null、undefined、false、空字符串、0、NaN), 那么就会返回第二个值。如果第一个值为真值,返回第一个值。
  • 一般用在处理默认值或者条件运算
  1. ?? 空值合并操作符
  • 如果第一个操作数是空值(例如 null 或 undefined),那么它就会返回第二个操作数的值。反之返回第一个值
  •  一般用于简化代码进行空值合
  1. ||逻辑或运算符 VS ??空值合并操作符
  • 值判断范围不同: || 判断是否为假值 , 而 ?? 主要针对null undefined
  • 用途稍有不同:|| 是逻辑运算符偏向逻辑处理, ??主要为了简化代码

JavaScript
        let info1 = 0
        info1 = info1 || '默认值'
        console.log(info1);//默认值

        let info2 = 0
        info2 = info2 ?? '默认值'
        console.log(info2);//0

 十二 箭头函数

(一)箭头函数实例

JavaScript
        var fn = () => {
            // {} 函数体
            // () 形参列表
        }

        // 当一个参数的时候 省略括号()
        var f1 = i => { }

        // 当函数体只有一句话的时候的时候 省略{}
        var f1 = i => console.log(i);

        // 当只有一个返回值的时候  return省略
        var f3 = i => 10

        // 当你返回的是一个对象 需要在函数体外部加上括号
        var f4 = i => ({ a: 1 })

        function Person(name) {
            this.name = name;
        }

        // 注意:箭头函数内没有this
        let Person = (name) => {
            this.name = name;
        }
        let p = new Person()

(二)哪些地方不能使用箭头函数(涉及this指向问题)

1.不能作为构造器,因为不能new(用this赋值)

2.在ES6中声明class类里的constructor函数,不能使用箭头函数

3.给原型对象添加方法的时候 不要使用箭头函数

十三 声明变量 let|const

1.let声明的特点

        1.let声明不会提升 (提升 但是没有初始化)

        2.let声明的变量不会挂载在window上

        3.let不能对变量重复声明

        4.let会和{}形成块级作用域

2.const声明(常量)特点

        1.不会提升 (提升 但是没有初始化)

        2.和{}形成块级作用域

        3.不能重复声明

        4.不能挂载在window(Go)上

        5.不能被改变

        6.声明的时候必须赋值

(二) let形成暂时性死区

JavaScript
        // 形成了暂时性死区
        // 由于let提升但是未初始化 导致在一片区域内 不能按照作用域链向上寻找变量
        // 这个区域叫暂时性死区
        var a = 1
        {
            console.log(a);//Cannot access 'a' before initialization
            let a = 2;//let声明提升但未初始化
        }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/815444.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

马上拥有“钞能力”!!24个Python接单平台,赶紧码住!!

学Python能兼职挣米吗&#xff1f;怎么挣&#xff1f; 一、Python兼职种类&#xff1a; 接私活刚学会python那会&#xff0c;就有认识的朋友介绍做一个网站的私活&#xff0c;当时接单赚了4K&#xff0c;后又自己接过开发网站后台接口、做数据处理等事情&#xff0c;都赚了一…

【机器学习300问】66、均方误差与交叉熵误差,两种损失函数的区别?

一、均方误差&#xff08;Mean Squared Error, MSE&#xff09; 假设你是一个教练&#xff0c;在指导学生射箭。每次射箭后&#xff0c;你可以测量子弹的落点距离靶心的差距&#xff08;误差&#xff09;。MSE就像是计算所以射击误差的平方后的平均值。它强调了每一次偏离靶心的…

了解 Vue 工程化开发中的组件通信

目录 1. 组件通信语法 1.1. 什么是组件通信&#xff1f; 1.2. 为什么要使用组件通信&#xff1f; 1.3. 组件之间有哪些关系&#xff08;组件关系分类&#xff09;&#xff1f; 1.4. 组件通信方案有哪几类 &#xff1f; 2. 父子通信流程图 3. 父传子 3.1. 父传子核心流程…

力扣练习题(2024/4/14)

1接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2…

SpringBoot 整合RocketMQ

目录 一、引入依赖 二、配置文件 三、生产者 四、消费者 五、结果 一、引入依赖 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.0</version> </d…

leetcode热题100.爬楼梯(从二进制到快速幂)

Problem: 70. 爬楼梯 文章目录 题目思路Code复杂度 题目 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方…

numpy学习笔记(5),其他实用函数

8. 更多函数 8.1 随机数 8.1.1 常用随机数 8.1.1.1 numpy.random.rand(d0, d1, …, dn) 返回[0.0, 1.0)随机浮点数&#xff0c;即大于等于0.0&#xff0c;小于1.0。d0, d1, …, dn&#xff1a;返回的数组形状 # 使用numpy.random.rand函数 import numpy as np np.random.r…

每日一题:无重复字符的最长子串

给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是"abc"&#xff0c;所以其长度为 3。示例 2: 输入: s "bbbbb" 输出: 1 解释: 因为无重…

2009-2021年上市公司僵尸企业识别数据(含原始数据+计算代码+计算结果)

2009-2021年上市公司僵尸企业识别数据&#xff08;含原始数据计算代码计算结果&#xff09; 1、时间&#xff1a;2009-2021年 2、指标&#xff1a; 证券代码 、证券简称、上市日期、year、净利润、政府补助、流动负债合计、负债合计、财务费用明细利息支出、资产总计、长期负…

(Oracle)SQL优化案例:隐式转换优化

项目场景 项目现场的某个kettle模型执行非常缓慢&#xff0c;原因在于某个SQL执行效率非常的低。甲方得知此事要求公司赶紧优化&#xff0c;负责该模块的同事对SQL优化并不熟悉。所以作为一个立志成为优秀DBA的ETL工程师&#xff0c;我自告奋勇&#xff1a;不是DBA&#xff0c;…

ES6 关于Class类的继承 extends(2024-04-10)

1、简介 类Class 可以通过extends关键字实现继承&#xff0c;让子类继承父类的属性和方法。extends 的写法比 ES5 的原型链继承&#xff0c;要清晰和方便很多。 class Foo {constructor(x, y) {this.x x;this.y y;console.log(父类构造函数)}toString() {return ( this.x …

《由浅入深学习SAP财务》:第2章 总账模块 - 2.7 总账模块报表 -2.7.1 对外报表:资产负债表及利润表

总账模块报表既包括对外报告的资产负债表、损益表、现金流量表&#xff0c;也包括企业自身用于查询和分析的各类报表&#xff0c;如科目余额表等。 2.7.1 对外报表&#xff1a;资产负债表及利润表 在SAP中&#xff0c;出具资产负债表和利润表的标准方法是先在后台建立一套“会…

971: 统计利用先序遍历创建的二叉树的深度

解法&#xff1a; 1.先序遍历创建二叉树链表形式 2.求二叉树的深度 用后序遍历实现&#xff1a; 1.后序遍历求节点A左右子树高度 2.对节点A&#xff1a; 1.取左右子树较大高度 2.返回高度1&#xff08;即以节点A为根节点的子树的最大深度&#xff09; 例如 #include <ios…

LINUX命令行后台运行matlab程序

UBUNTU安装了matlab&#xff0c;需要后台运行matlab程序。 一、MobaXterm程序&#xff08;非后台&#xff09; 使用mobaxterm程序&#xff0c;ssh连接ubuntu&#xff0c;在对应账号中输入matlab&#xff0c;即可基于mobaxterm自带的Xserver可视化界面&#xff0c;打开matlab界…

RobotFramework功能自动化测试框架基础篇

概念 RobotFramework是什么&#xff1f; Robot Framework是一款python编写的功能自动化测试框架。具备良好的可扩展性&#xff0c;支持关键字驱动&#xff0c;可以同时测试多种类型的客户端或者接口&#xff0c;可以进行分布式测试执行。主要用于轮次很多的验收测试和验收测试…

网页的基本结构

VScode中HTML的自动补全&#xff1a; 自动补全&#xff1a;例如标签 <h1></h1> 1.输入<h1>后其会自动给其补全 2. 进输入h1 tab键 网页的基本结构&#xff1a; 网页的基本结构只需要在VScode当中输入&#xff1a;&#xff01; tab键即可 <!DOCTYPE html…

ARM v8 Cortex R52内核 08 内存保护单元 Memory Protection Unit

ARM v8 Cortex R52内核 08 内存保护单元 Memory Protection Unit 8.1 About the MPU Cortex R52 处理器具有两个可编程的MPU&#xff0c;由EL1和EL2控制。每个MPU允许将4GB内存地址划分为多个区域。 每个内存区域由基地址、限制地址、访问权限和内存属性定义。 对于数据访问…

阿里对象储存OSS的SDK使用

对象存储OSS 该功能的实现使用了阿里的&#xff1a;对象存储OSS技术。 在阿里对象存储空间的文件可以 以链接 的形式进行访问: 文件访问路径规则 &#xff1a;https://BucketName.Endpoint/ObjectName 该技术的使用方式有很多&#xff0c;针对于SDK的简单实现官网上也有教程…

【网络编程】高性能并发服务器源码剖析

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的网络编程系列之洪水网络攻击&#xff0c;在这篇文章中&#xff0c;你将会学习到在网络编程中如何搭建一个高性能的并发服务器&#xff0c;并且我会给出源码进行剖析&#xff0c;以及手绘UML图来帮助大家来理解&#xf…

教你将配置好的conda环境迁移到其它设备

文章目录 问题分析存在的方法环境要求方法步骤1. 下载conda pack2. 打包原环境3. 新设备还原环境4. 查看环境 问题分析 好不容易配置好的conda环境&#xff0c;要在另一个设备上运行&#xff0c;还要重新配置&#xff0c;好麻烦。 存在的方法 pip install -r requirement.txt …