【菜狗学前端】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声明提升但未初始化
        }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年广东省网络系统管理样题第3套网络部署部分

2024年广东省网络系统管理样题第3套网络部署部分 模块A&#xff1a;网络构建 极安云科专注职业教育技能培训4年&#xff0c;包含信息安全管理与评估、网络系统管理、网络搭建等多个赛项及各大CTF模块培训学习服务。本团队基于赛项知识点&#xff0c;提供完整全面的系统性理论教…

Bridge 桥接

意图 将抽象部分与其显示部分分离&#xff0c;使他们都可以独立地变化。 结构 其中&#xff1a; Abstraction定义抽象类的接口&#xff0c;维护一个指向Implementer类型对象的指针。RefinedAbstraction扩展由Abstraction定义的接口。Implementor定义实现类的接口&#xff0c…

并发编程之ThreadLocal使用及原理

ThreadLocal主要是为了解决线程安全性问题的 非线程安全举例 public class ThreadLocalDemo {// 非线程安全的private static final SimpleDateFormat sdf new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public static Date parse(String strDate) throws ParseExc…

Spring源码刨析之配置文件的解析和bean的创建以及生命周期

public void test1(){XmlBeanFactory xmlBeanFactory new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));user u xmlBeanFactory.getBean("user",org.xhpcd.user.class);// System.out.println(u.getStu());}先介绍一个类XmlBeanFac…

服务器主机关机重启告警

提取时间段内系统操作命名&#xff0c;出现系统重启命令&#xff0c;若要出现及时联系确认 重启命令&#xff1a; reboot / init 6 / shutdown -r now&#xff08;现在重启命令&#xff09; 关机命令&#xff1a; init 0 / shutdown -h now&#xff08;关机&#…

防汛物资仓库管理系统|实现应急物资仓库三维可视化

系统概述 智慧应急物资仓库可视化系统&#xff08;智物资DW-S300&#xff09;采用了 B/S 架构的设计&#xff0c;通过浏览器即可快速登录操作。实现对库房内的应急物资从申购入库、出库、调拨、库内环境监测、维修保养、检测试验、处置报废等全周期、科学、规范的管理。系统以…

恢复MySQL!是我的条件反射,PXB开源的力量...

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

如何进行计量经济分析

计量经济分析是定量分析的常用方法&#xff0c;在经济分析领域有着广泛且重要的应用。计量经济分析以一定的经济理论和统计数据为基础&#xff0c;运用数学、统计学相关方法&#xff0c;通过建立计量模型&#xff0c;并运用软件进行操作&#xff0c;从而实现对经济问题的定量分…

时间序列模型:lag-Llama

项目地址&#xff1a;GitHub - time-series-foundation-models/lag-llama: Lag-Llama: Towards Foundation Models for Probabilistic Time Series Forecasting 论文地址&#xff1a;https://arxiv.org/pdf/2310.08278.pdf hugging-face镜像&#xff1a;https://hf-mirror.c…

QQ农场-phpYeFarm添加数据教程

前置知识 plugin\qqfarm\core\data D:\study-project\testweb\upload\source\plugin\qqfarm\core\data 也就是plugin\qqfarm\core\data是一个缓存文件,如果更新农场数据后,必须要删除才可以 解决种子限制(必须要做才可以添加成功) 你不更改加入了id大于2000直接删除种子 D…

Unity类银河恶魔城学习记录12-14 p136 Merge Skill Tree with Sword skill源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili CharacterStats.cs using System.Collections; using System.Collections.…

如何搭建SearXNG搜索引擎

小白如何搭建SearXNG搜索引擎 前言 国内用户在使用百度、360、搜狗等主流搜索引擎时&#xff0c;面临搜索结果精确度不高、广告泛滥及隐私顾虑等问题。虽然Google以其出色性能备受推崇&#xff0c;但由于无法在国内访问&#xff0c;部分用户转而选择Bing作为折衷方案&#xff…

LeetCode617:合并二叉树

题目描述 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新二叉树。合并的规则是&#xff1a;如果两个节点重…

OSCP靶场--PayDay

OSCP靶场–PayDay 考点(公共exp文件上传密码复用sudo -l all提权) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC 192.168.153.39 -p- -Pn --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-13 04:52 EDT Nmap scan report for 192…

计算机网络——ARP协议

前言 本博客是博主用于复习计算机网络的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 这篇博客是在B站掌芝士zzs这个UP主的视频的总结&#xff0c;讲的非常好。 可以先去看一篇视频&#xff0c;再来参考这篇笔记&#xff08;或者说直接偷走&#xff09;。 …

Spark-机器学习(1)什么是机器学习与MLlib算法库的认识

从这一系列开始&#xff0c;我会带着大家一起了解我们的机器学习&#xff0c;了解我们spark机器学习中的MLIib算法库&#xff0c;知道它大概的模型&#xff0c;熟悉并认识它。同时&#xff0c;本篇文章为个人spark免费专栏的系列文章&#xff0c;有兴趣的可以收藏关注一下&…

双子座 Gemini1.5和谷歌的本质

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

流媒体的安全谁来保障

流媒体的安全谁来保障 说起媒体&#xff0c;我们马上就会想到报纸新闻、广播、电视。 其实所谓的流媒体同我们通常所指的媒体是不一样的&#xff0c; 它只是一个技术名词。流媒体到底是什么&#xff1f;能给我们的生活带来什么&#xff1f;跟小德一起来看看。 流媒体是什么&a…

缓存与数据库的数据一致性解决方案分析

在现代应用中&#xff0c;缓存技术的使用广泛且至关重要&#xff0c;主要是为了提高数据访问速度和优化系统整体性能。缓存通过在内存或更快速的存储系统中存储经常访问的数据副本&#xff0c;使得数据检索变得迅速&#xff0c;从而避免了每次请求都需要从较慢的主存储&#xf…

LeetCode 0705.设计哈希集合:很多人都是这样做的吧【逃】

【LetMeFly】705.设计哈希集合&#xff1a;很多人都是这样做的吧【逃】 力扣题目链接&#xff1a;https://leetcode.cn/problems/design-hashset/ 不使用任何内建的哈希表库设计一个哈希集合&#xff08;HashSet&#xff09;。 实现 MyHashSet 类&#xff1a; void add(key…