ES6-ES11核心知识点

450 阅读16分钟

ES6

let

let a = 1,b = 2
let a,b
//1.let不能在相同作用域重复声明,var可以
let a = 1
let a = 2//报错
//2.块级作用域 全局,函数,eval
//3.不存在变量提升,提前使用报错
//4.不影响作用域链
{
    let a = 1
    function fn(){
        consloe.log(a)
    }
    fn()//1
}
console.log(a)//报错

const

const A = 'lei'
//1.声明必须赋初始值
//2.常量使用大写(好区分)
//3.常量的值不能修改,赋值对象其存储的地址值不能改,但其对象内部数据不管,数组不算
//4.块级作用域

变量的解构赋值

ES6中允许按照一定模式从数组对象中提取值。对变量进行赋值,相当于破坏其原有结构,直接将值赋给新变量,下次直接用新变量就行

//1.数组解构
const arr = ['A','B','C']
let [a,b,c] = arr

console.log(a)//A
console.log(b)//B
console.log(c)//C

//2.对象解构
const obj = {
    name:'lei',
    age:23city: function(){
        console.log("重庆")
    }
}
//属性名和变量名要一样!
let {name,age,city} = obj
console.log(name)//lei
console.log(age)//23
console.log(city)//function
city()//重庆

模板字符串

let str = [`字符串`]
//1.可以有HTML标签
//2.变量拼接
let str ='ssss'
let str1 = 'aaaa'
let str2 = `${str}${str1}`

简化对象写法

ES6允许在大括号里面,直接写入变量和函数,前提要声明赋值,作为对象的属性和方法

let name = 'a'
let change = function(){
    console.log("b")
}
const sss = {
    name,
    change,
    //improve:function(){
        //console.log("b")
    //}  方法简写
    improve(){
        console.log("b")
    }
}

箭头函数

let fn = (a,b) => {// =>相当于function
    return a+b
}
fn(1,2)//3

//1.this静态,this 总是指向 函数定义时 所在 作用域 下的this值!任何方式均不能改变指向
function getName() {
    console.log(tihs.name)
}
let getName2 = () => {
    console.log(tihs.name)
}
const city = {
    name:'重庆'
}
window.name = '成都'
//直接调用,均为成都
//call
getName.call(city)//重庆
getName2.call(city)//成都

//2.不能作为构造函数去实例化对象
//3.不能使用arguments变量
//4.箭头函数简写
	//1)省略(),当形参有且只有一个
	let add = n =>{
        return n+n
    }
	//2)省略{},当代码体只有一条语句,此时return省略,且执行结果就是函数返回值
    let add = n =>  n+n
    console.log(add(3))//6

//箭头函数适合与 this无关 的回调,如计时器,数组方法回调

参数默认值设置

//1.形参默认值,有默认值的一般靠后
function add(a,b=2){
    return a + b
}
let c = add(1)
console.log(c)//3

//2.与解构赋值结合
function con({v1,v2,v3='c'}){
    console.log(v1)
    console.log(v2)
    console.log(v3)
}
//调用con函数     相当于 {v1,v2} = {v1:'a',v2:'b'} //解构赋值
con({
    v1:'a',
    v2:'b'
})//a b c

rest参数

获取函数的实参,代替arguments

//ES5获取实参的方式
function data(){
    console.logarguments)
}
data('a','b','c')//返回的对象
//rest参数,必须放到参数的最后!
function data(A,...args){
    console.log(A,args)
}
data('a','b','c')//a ['b','c'] 

...扩展运算符

将数组转换为逗号分隔的参数序列,化整为散

const name = ['a','b','c']
function fn(){
    console.log(arguments)//返对象
}
fn(name)//{['a','b','c']}  fn(['a','b','c'])
fn(...name)//{'a','b','c'} fn('a','b','c')

//1.数组合并
const a1 = ['1','2']
const a2 = ['3','4']
const a3 = [...a1,...a2]
console.log(a3)//['1','2','3','4']
//2.数组克隆
const b1 = [5,6,7]
const b2 = [...b1]
console.log(b2)//[5,6,7]  浅拷贝 有引用数据类型也是 拷贝其地址值
//3.伪数组转真数组
const divs = documentquerySelectorAll('div')
const divArr = [...divs]

Symbol

ES6新引入的原始数据类型,表示独一无二的值,类似于字符串的数据类型

特点:

  • 值是唯一的,用来解决命名冲突的问题
  • 不能与其他数据进行运算
  • 其定义的对象属性不能使用for...in循环遍历,但可以使用Reflect.ownKeys来获取对象的所有键名
let s = Symbol()//Symbol不是一个 构造 函数,所以s不是实例对象
console.log(s,typeof s)//Symbol() "symbol"
let s1 = Symbol('描述字符串')
let s2 = Symbol('描述字符串')
console.log(s1 === s2)//false   描述可以相同,但其id不同有点类似不同对象的地址值

//Symbol.for 创建  Symbol为函数对象
let s3 = Symbol.for('a')
let s4 = Symbol.for('a')
console.log(s3 === s4)//true
//不能与其他数据进行运算(任何)

//向对象添加属性和方法
let game = {...
//再声明一个对象            
let methods = {
    up:Symbol("向上"),
    down:Symbol("向下")
}//注意这两个相同,可以理解为俩个地址值

//添加
game[methods.up] = function(){
    console.log("上")
}
game[methods.down] = function(){
    console.log("下")
}
//尽管原对象内有up或者down的方法也不影响,相当于加的Symbol("向上")和Symbol("向下"),独立的


let game ={
    name:'lol',
    [Symbol('hero')]:function(){//Symbol('hero')动态的并不跟name一样固定所以加[]
        console.log('yasuo')
    }
}

console.log(game)//要调用Symbol则在外部声明变量存储,属性名改为变量,再对象.方法调用

Symbol内置属性

//自定义类型检测
class Person{
    static [Symbol.hasInstance](param){
        console.log(param)
    }
}
let o = {}
console.log(o instanceof Person)

//决定数组是否展开
const arr = [1,2,3]
const arr1 = [2,2,3]
arr1[Symbol.isConcatSpreadable] = false//Symbol属性再作为对象属性的扩展
console.log(arr.concat(arr1))//[1, 2, 3, Array(3)]

迭代器

一种接口,部署Iterator接口(对象里的一个属性,Symbol.iterator),完成遍历

  1. ES6创造了一种新的遍历命令 for...of循环,由Iterator操作
  2. 能具备iterator接口的数据
    1. Arry
    2. Arguments
    3. Set
    4. Map
    5. String
    6. TypedArray
    7. NodeList
/* const arr = ['a','b','b']
for(let a in arr){//in 是索引
    console.log(a)//0,1,2
}
 */
//迭代器
for(let a of arr){//of 是键值
    console.log(a)//'a','b','b'
}
  1. 工作原理

    1. 创建一个指针对象,指向当前数据结构的起始位置
    2. 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
    3. 接下来不断调用next方法,指针一直往后移动,直到最后一个成员
    4. 每调用next方法返回一个包含value和done属性的对象

    【注意】需要自定义遍历数据时,要想到使用迭代器

const name = ['a','b','c']
//创建指针对象
let iterator = name[Symbol.iterator]()
//调用对象的next方法
console.log(iterator.next())//{value: 'a', done: false}
console.log(iterator.next())//{value: 'b', done: false}
console.log(iterator.next())//{value: 'c', done: false}
console.log(iterator.next())//{value: undefined, done: true}


//迭代器应用
//声明一个对象
const ban = {
    name:'a',
    stu:[
        'x',
        'y',
        'z'
        ],
        [Symbol.iterator](){
            //索引变量
            let index = 0
            let _this = this
            return {
                next:function(){
                    if(index < _this.stu.length){
                        const res =  {value:_this.stu[index],done:false}
                        //下标自增
                        index++
                        //返回结果
                        return res
                    }else{
                        return {value:undefined,done:true}
                    }
                }
            }
        }
}
//针对性遍历这个对象
for(let i of ban){
    console.log(i)
}

生成器函数

ES6提供的一种异步编程解决方案,一种特殊的函数

function * gen (){// * 生成器函数
    console.log('a')
    yield 'lllll'// yield函数代码分隔符  类型matlab间隔符执行
     console.log('b')
}

let ietrator = gen ()//迭代器对象
ietrator.next()//a  是一个迭代器 ,需要next()才能输出,跟传统函数有出入
ietrator.next()//b
/*            *******                        */
function * gen (){// * 生成器函数
    yield 'lllll'// yield函数代码分隔符  类型matlab间隔符执行
	yield 'aaaaaa'
    yield 'vbbbbb'
}

let ietrator = gen ()//迭代器对象
console.log(ietrator.next())//{value: 'lllll', done: false}
console.log(ietrator.next())//{value: 'aaaaaa', done: false}
console.log(ietrator.next())//{value: 'vbbbbb', done: false}
console.log(ietrator.next())//{value: undefined, done: true}

for(let i of gen()){
    console.log(i)
}//lllll aaaaaa vbbbbb

生成器函数参数

function * gen (arg){// * 生成器函数
    console.log(arg)//AAA
	let one = yield 'lllll'// yield函数代码分隔符  类型matlab间隔符执行
    console.log(one)//BBB
	let two = yield 'aaaaaa'
    console.log(two)//CCC
    let three = yield 'vbbbbb'
    console.log(three)//DDD
}

let ietrator = gen ('AAA')//迭代器对象
console.log(iterator.next());
console.log(iterator.next('BBB'));//传入one  第二次调用作为第一次yield语句的返回结果
console.log(iterator.next('CCC'));//传入two
console.log(iterator.next('DDD'));//传入three

生成器函数实例

//异步编程  文件操作  网络操作(ajax,request)数据库操作
//1s后 控制台输出 111 2s后输出222 3s后输出333
//回调地狱 不停回调 一直嵌套
setTimeout(() => {
    console.log(111)
    setTimeout(() => {
        console.log(222)
        setTimeout(() => {
            console.log(333)
        }, 3000);
    }, 2000);
}, 1000);

//生成器函数解决回调地狱
function one(){
    setTimeout(() => {
        console.log(111)
        iterator.next()//调用执行yield two()

    }, 1000);
}
function two(){
    setTimeout(() => {
        console.log(222)
        iterator.next()//调用执行yield three()

    }, 2000);
}
function three(){
    setTimeout(() => {
        console.log(333)
        iterator.next()//调用执行.......可以解决回调地狱

    }, 3000);
}
function * gen(){//依次迭代调用
    yield one()
    yield two()
    yield three()
}
//调用生成器函数
let iterator = gen()
iterator.next()//每调用一次执行一次


//生成器函数依次获取用户数据 订单数据 商品数据
function users(){
    setTimeout(() => {
        let data = 'user'
        ite.next(data)//第二次调用执行yield orders() 并将data作为参数传入users

    }, 1000);
}
function orders(){
    setTimeout(() => {
        let data = 'orders'
        ite.next(data)//调用执行yield goods() 参数传入orders

    }, 1000);
}
function goods(){
    setTimeout(() => {
        let data = 'goods'
        ite.next(data)//第四次调用,参数传入goods

    }, 1000);
}
function * gen(){//依次迭代调用
    let users1 = yield users()
    console.log(users1)
    let orders1 = yield orders()
    console.log(orders1)
    let goods1 = yield goods()
    console.log(goods1)
}
let ite = gen()
ite.next()//第一次调用 yield users()

*Promise

ES6引入的异步编程新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果

  1. Promise 构造函数:Promise(excutor){}
  2. Promise.prototype.then 方法
  3. Promise.prototype.catch 方法
//实例化Promise对象
const p = new Promise(function(resolve,reject){
    setTimeout(() => {
/*         let data = 'data'
        resolve(data)//执行resolve表明调用成功 */
        let data = 'error'
        reject(data)//执行reject表明调用失败,执行.then中的第二个回调函数
    }, 1000);
})

//调用promise对象的then方法
p.then(function(value){
    console.log(value)//执行resolve后
},function(reson){
    console.log(reson)//执行reject后
})
//Promise封装AJAX请求       
//接口地址:https://api.apiopen.top/getJoke
        const p =new Promise((resolve,reject) => {
        //1.创建对象
        const xhr = new XMLHttpRequest()
        //2.初始化
        xhr.open("GET","https://api.apiopen.top/getJoke")
        //3.发送
        xhr.send()
        //4.绑定事件
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4){
                if(xhr.status>=200&&xhr.status<300){
                   //请求成功
                    resolve(xhr.response)
                }else{
                    //请求失败
                    reject(xhr.response)
                }
            }
        }
    })
//把请求结果提取出来,在外面进一步处理,不用在内部处理
    p.then(function(value){
        console.log(value)
    },function(reason){
        console.error(reason)
    })
        //创建promise对象
        const p = new Promise((resolve,reject)=>{
            setTimeout(() => {
                resolve('data')
                //reject('error')
            }, 1000);
        })
//then 方法的返回结果是Promise对象,对象状态由回调函数的执行结果决定
//1.如果回调函数中返回的结果是 非Promise类型的属性(数值、字符串、不返回undefined等),状态为成功,返回值为对象的成功的值
//2.如果返回结果是promise对象,则该该promise对象的状态类型是什么返回的就是什么
//3.若抛出错误,则promise的返回rejected,且其值是抛出的值
        const result = p.then(value => {
            //1.非promise类型的属性
            return 123//执行则其状态为成功其result的成功值为123
            //2.是promise对象
             return new Promise((resolve,reject)=>{
                resolve('OK')
            }) 
            //3.抛出错误
           throw new Error("出错")
        },reason => {
            console.warn(reason)
        }) 
        //4.链式调用 嵌套异步任务
        p.then(value=>{

        },reason=>{

        }).then(value=>{

        },reason=>{

        })
        console.log(result)

Promise实践

//引入fs模块
const { rejects } = require("assert")
const fs = require("fs")
const { resolve } = require("path/win32")

/* fs.readFile('文件.md',(err,data1)=>{
    fs.readFile("文件2.md",(err,data2)=>{
        fs.readFile("文件3.md",(err,data3)=>{
            let result = data1+'\r\n'+data2+'\r\n'+data3
            console.log(result)
        })
    })
}) *///传统方法实现易造成回调地狱


//使用Promise实现
const p = new Promise((resolve,reject)=>{
    fs.readFile('文件.md',(err,data)=>{//第一个异步任务
        resolve(data)
    })
})

p.then(value=>{//value第一个文件内容
    //为避免回调地狱,再次搞一个promis对象,将其提出,再次.then
    return new Promise((resolve,reject)=>{//第二个异步任务
        fs.readFile('文件2.md',(err,data)=>{//data第二个文件内容
        resolve([value,data])//成功,返回也是成功
        })
    })
}).then(value=>{//一个包含文件和文件2内容的数组
    return new Promise((resolve,reject)=>{//第三个异步
        fs.readFile('文件3.md',(err,data)=>{//data第三个文件内容
        value.push(data)//数组压入
        resolve(value)//成功 返回也成功
        })
    })
}).then(value=>{//所有文件的数组
    console.log(value.join('\r\n'))
})

Pormise对象catch方法

        const p = new Promise((value,reject)=>{
            setTimeout(() => {
                reject("出错!")
            }, 1000);
        })
/*         p.then(value=>{},reason=>{
            console.error(reason)
        }) */
        //then方法不指定第一个参数,即catch
        p.catch(reason=>{
            console.warn(reason)
        })

Set

let s = new Set()//集合  不重复唯一 只有键
//元素个数
console.log(s.size)
//添加新元素
s.add("aaa")
//删除元素
s.delete("aaa")
//检测元素
s.has("aaa")
//清空
s.clear()

//集合有迭代器的接口,所以可以用for...of遍历
for(let i of s){
    console.log(i)
}

集合实践

        let arr = [1,2,2,3,4,6]
        //1.数组去重
        //先将其变为 集合 去重
        //将 集合 转为 数组
        //let s = [...new Set(arr)]
        //console.log(s)
        //2.交集
        let arr2 = [4,5,6,5,6]
        /* let result = [...new Set(arr)].filter(items=>{
            let s2 = new Set(arr2)//4 5 6 集合
            if(s2.has(items)){
                return true
            }else{
                return false
            }
        }) */
        //简化写法
        //let result = [...new Set(arr)].filter(items=>new Set(arr2).has(items))
        //console.log(result)
        //3.并集
        //let union = [...new Set([...arr2,...arr])]
        //console.log(union)
        //4.差集
        let diff = [...new Set(arr)].filter(items=>!(new Set(arr2).has(items)))
        console.log(diff)

Map

键值对的集合,其“键”不限于字符串,可以是各种类型,Map也实现了iterator接口和扩展运算符,升级版对象,其属性可以是其他类型不只字符串

let m = new Map()
//添加元素
m.set("a",1)
m.set("fn",function(){
    console.log("b")
})
let key = {
    name:"let"
}
m.set(key,["a","b","c"])
//size获取元素个数
//delete删除元素
//get获取元素
//clear清空
//for...of遍历 [键,值]

Class类

对象的模板,可以看作一个语法糖

        //手机
/*         function Phone(brand,price){
            this.brand = brand
            this.price = price
        }
        //添加方法
        Phone.prototype.call = function(){
            console.log("打电话")
        }
        //实例化对象
        let xiaomi = new Phone("小米",2000)
        xiaomi.call()
        console.log(xiaomi) */

        //class
        class Phone{
            //构造函数 名字不能修改
            constructor(brand,price){
                this.brand = brand
                this.price = price
            }
            //方法必须使用该语法,不能使用ES5的对象完整形式即a:funciton(){}
            call(){
                console.log("打电话!")
            }
        }
        let oppo = new Phone("a",2000)
        console.log(oppo)

类的静态成员

class Phone{
    //静态属性
    static name = '手机'
	static change(){
        console.log("a")
    }
}
let n = new Phone()//实例对象的属性与构造函数的属性并不相同,两个不同对象其在堆内存位置都不同
console.log(n.name)//undefined
console.log(Phone.name)//手机

类继承

//ES5
function Phone(brand,price){//父类型
    this.brand = brand
    this.price = price
}
Phone.prototype.call = function(){
    console.log("打电话")
}
//智能手机 子类型
function SmartPhone(brand,price,color,size){
    Phone.call(this,brand,price)//改变this指向,指向SmartPhone的new的实例对象
    this.color = color//this指向该构造函数new的对象
    this.size  = size
}
//设置子级构造函数的原型
SmartPhone.prototype = new Phone() //为了调用父类方法,但改变了constrcutor指向
//console.log(SmartPhone.prototype.constructor)//指向Phnoe,意思是Phone是其构造函数,很明显该是SmartPhone
SmartPhone.prototype.constructor = SmartPhone
//声明子类的方法
SmartPhone.prototype.phtot = function(){
    console.log("拍照")
}
const iPhone = new SmartPhone("a",2500,'b',5)
console.log(iPhone)

//class
//可以明显看出通过class的类继承简洁很多,不需要设置子集构造函数的原型和constructor
class Phone{//构建父类
    constructor(brand,price){
        this.brand = brand
        this.price = price
    }
    call(){
        console.log("打电话")
    }
}

//子类
class SmartPhone extends Phone {
    constructor(brand,price,size){
        super(brand,price)//Phone.call(this,brand,price)
        this.size = size
    }
    photo(){
        console.log("拍照")
    }
    //对父类方法的重写 ,对于调用父类的方法若子类自身含有重名则必定调用自己的而不是父类,super()也不行
    call(){
        console.log("视频通话")
    }
}

const xiaomi = new SmartPhone('小米',"800","大")
console.log(xiaomi)
xiaomi.call()

get和set

        class Phone {
            get price () {//调用属性就执行内部的函数,类似动态监控
                console.log("属性被调用")
                return "true"
            }

            set price(newVal){//监控更新数据
                console.log("被赋新值")
            }
        }

        const obj = new Phone()
        console.log(obj.price)
        obj.price = "100"

Number方法扩展

        //0.Number.EPSILON 是 JS 表示的最小精度 其值接近2.22E-16
        console.log(0.1+0.2 === 0.3)//false
        function equal(a,b){
            if(Math.abs(a-b)<Number.EPSILON){
                return true
            }else{
                return false
            }
        }
        console.log(equal(0.1+0.2,0.3))//true
        //1.二进制和八进制
        let b = 0b1010//2进制
        let o = 0o777//8进制
        let d = 100
        let x = 0xff//16进制
        //2.检测一个数值是否为有限数  Number.isFinite
        console.log(Number.isFinite(01))//true
        console.log(Number.isFinite(100/0))//false
        console.log(Number.isFinite(Infinity))//false
        //3.检测一个数值是否为 NaN  Number.isNaN
        //4.Number.parseInt Number.parseFloat 将字符串转为整数或浮点数(只返回数值部分,过滤字符部分)
        console.log(Number.parseInt('11是1啊s'))//11
        console.log(Number.parseFloat('5884588啊s'))//5884588
        //5.Number.isInteger 判断一个数是否为整数
        //6.Math.trunc 抹去小数部分
        //7.Math.sign 判断一个数是正数 负数  还是 零
        console.log(Math.sign(100))//1
        console.log(Math.sign(0))//0
        console.log(Math.sign(-5))//-1

Object方法扩展

        //1.Object.is 判断两个值是否完全相等
        console.log(Object.is(120,120))//true
        console.log(Object.is(NaN,NaN))//true
        console.log(NaN === NaN)//false
        //2.Object.assign 对象合并
        const p1 = {
            a:"1",
            b:"2",
            c:"3"
        }
        const p2 = {
            a:"A",
            b:"B"
        }
        //p1为基础模板,p2若有其对于属性则覆盖没有则不覆盖
        console.log(Object.assign(p1,p2))//{a: 'A', b: 'B', c: '3'}
     	//还可以用...拓展运算符合并(ES9)
		console.log({...p1,...p2})
        //3.Object.setPrototypeOf 设置原型对象  Object.getPrototypeOf获取原型对象
        const s1 = {
            name:"a"
        }
        const s2 = {
            city:"b"
        }
        Object.setPrototypeOf(s1,s2)//对s1对象的原型上设置
        console.log(Object.getPrototypeOf(s1))
//ES8
//Object.values Object.entries
//1.Object.values()返回一个给定对象的 所有 可枚举属性的 数组
//2.Object.entries()返回一个给定对象 自身 可遍历属性[key,value]的 数组 可以创建Map
const m = new Map(Object.entries(s))
//对象属性的描述对象
Object.getOwnPropertyDescriptors()

模块化

将一个大的程序文件**,拆分**成许多小的文件,然后将小文件组合起来

好处:

  • 防止命名冲突
  • 代码复用(各部分独立互不干预)
  • 高维护性

语法

模块化功能主要由两个命令构成:export和import

  • export命令用于规定模块的对外接口(这样就不需要导入整个文件而是其中一些数据比如一个最终结果)
  • import命令用于输入其他模块提供的功能
//分别暴露
 export let s = "a"

export function fn(){
    console.log("bbbbb")
}
 

//统一暴露

 let s = "a"

function fn(){
    console.log("bbbbb")
}

export {s,fn} 

        import * as module from "./module.js"
        console.log(module)//Symbol

//默认暴露
export default{
    a:"1",
    fn:function(){
        console.log("ssss")
    }
}
//调用
        import * as module from "./module.js"
        module.default.fn()

模块引入方式

        //1.通用导入方式
        //引入 module.js
        import * as module from "./module3.js"
        console.log(module.default.a)
        //2.结构赋值形式
        import {s,fn} from "./module1.js"//分别暴露
        import {s as s1,fn as fn1} from "./module2.js"//统一暴露
        import {defualt as m3} from "./module3.js"//默认暴露 default要有别名
        //3.简便形式 针对默认暴露
        import m3 from"./module3.js"

ES7

  1. Array.prototype.includes

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

  2. 指数操作符

    **,用来实现幂运算,功能与Math.pow结果相同

ES8

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

async

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

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

            //async函数
            async function fn(){
                return "aaaa"
            }
            console.log(fn())//promise对象 成功
    

【注】返回的不是promise类型的对象都是成功promise,但若抛出错误则返回失败promise对象,返回的一个promise对象,根据该promise成功与否决定返回的promise对象的值,即一一对应

await

  1. 必须写在async函数内
  2. await右侧的表达式一般为promise对象
  3. await返回的是promise成功的值
  4. await的promise失败,则会抛出异常,需要通过try...catch捕获处理
        //await 要处于 async中,单向依赖
        const p = new Promise((resolve,reject)=>{
            //resolve("a")
            reject("warn")
        })
        async function fn(){
        try{//resolve
            let result = await p
            console.log(result)
        }catch(e){//reject
            console.log(e)
        }
    }
        fn()

//1.引入fs模块
const { rejects } = require("assert")
const fs = require("fs")
const { resolve } = require("path/posix")
//读取文件
function read1(){
    return new Promise((resolve,reject)=>{
    fs.readFile("文件.md",(err,data)=>{
        if(err) reject(err)
        resolve(data)
    })
})
}
function read2(){
    return new Promise((resolve,reject)=>{
    fs.readFile("文件2.md",(err,data)=>{
        if(err) reject(err)
        resolve(data)
    })
})
}
function read3(){
    return new Promise((resolve,reject)=>{
    fs.readFile("文件3.md",(err,data)=>{
        if(err) reject(err)
        resolve(data)
    })
})
}

//声明async函数
async function main(){
    //获取文件内容
    let a1 = await read1()
    let a2 = await read2()
    let a3 = await read3()
    console.log(a1.toString())
    console.log(a2.toString())
    console.log(a3.toString())

}
main()

async和await封装ajax请求

  		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)//返回给promise对象
                    }else{
                        reject(x.response)
                    }
                }
            }
        })
        }

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

        //async await 测试 axios
        async function fn(url) {
            const b =  await sendAJAX(url)//返回一个成功的promise对象且其值为成功值
            console.log(b)
        }
        let url = "https://api.apiopen.top/getJoke"
        fn(url)

ES9

对象展开

//在ES6中的rest参数只针对数组
//ES9中为 对象 提供了像数组一样的rest 参数和扩展运算符
        function connect({host,port,...a}) {//...a 对象{user:'b',pass:22222}
            console.log(host)
            console.log(port)
            console.log(a)
        }
        connect({
            host:'a',
            port:1020,
            user:'b',
            pass:22222
        })

正则命名扩展

//一般捕获
let str = "<a href='aaaaaaaaaaa'>bbbb</a>"
const reg = /<a href='(.*)'>(.*)<\/a>/
const result = reg.exec(str)
console.log(result[1])
console.log(result[2])
//捕获分组(对象)
let str = "<a href='aaaaaaaaaaa'>bbbb</a>"
const reg = /<a href='(?<url>.*)'>(?<text>.*)<\/a>/  //url和text是分组属性名
const result = reg.exec(str)
console.log(result.groups.url)

反向断言

//正向断言
let str = 'asdasdasda你你你77零零零零'
const reg = /\d+(?=零)/
const result = reg.exec(str)//77
//反向断言
let str = 'asdasdasda你你你77零零零零'
const reg = /(?<=你)\d+/
const result = reg.exec(str)//77

dotAll模式

一般针对HTML结构的换行处理/.*?/s

ES10

Object.fromEntries

//二维数组或者Map
//转为对象

Object.entries

//将对象转为数组,且为[key,value]形式

trimStart&trimEnd

//str.trimStart() 左边空白
//str.trimEnd()   右边空白

Array.prototype.flat&Array.prototype.flatMap

//flat 平
//多维转低维
arr.flat(n)//n是深度
//flatMap
//map返回结果若是多维数组再经过flat降维
arr.flatMap

ES11

私有属性

 class Person{//私有属性除非自身输出,不然外部是调用不了的
        //共有属性
        name
        //私有属性
        #age
        constructor(name,age){
            this.name = name
            this.#age = age
        }
        infor(){
            console.log(this.name)
            console.log(this.#age)
        }
    }
    const p = new Person('aa',21)
    p.infor()

promise.allSettled

const p1 = new Promise((resolve,reject)=>{
    setTimeout(() => {
        resolve("1111")
    }, 1000);
})
const p2 = new Promise((resolve,reject)=>{
    setTimeout(() => {
        reject("2222")
    }, 1000);
})

//调用allSettled方法
//const result = Promise.allSettled([p1,p2])//返回一个promise对象,且都是成功状态,其结果值是一个数组,数组内是对象,对象中为返回结果状态信息和具体值
const res = Promise.all([p1,p2])//所有promise对象有一个失败就是失败得到失败的值,只有全部成功才返回所有成功的promise值
console.log(res)

Srting.prototype.matchAll

//正则批量匹配
        let str = `<ul>
        <li>
            <a>啊啊啊</a>
            <p>对对对对对</p>
        </li>
        <li>
            <a>哇哇哇哇</a>
            <p>水水水水</p>
        </li>
    </ul>`
    //声明正则
    const reg = /<li>.*?<a>(.*?)<\/a>.*?<P>(.*?)<\/p>/sg
    //调用方法
    const result = str.matchAll(reg)//返回 可迭代对象 for...of
        const arr = [...result]
        console.log(arr)

可选链操作符

function main(config) {
    //const dbHost = config && config.db &&config.db.host
    const dbHost = config?.db?.host
    console.log(dbHost)
}
main({//没有也不报错,返undefined
    db:{
        host:'aaa'
    }
})

动态import加载

const btn =document.getElementById('btn')
btn.onclick = function () {//动态导入的模块为promise对象,其.then的返回值为js文件中export的代码
    import('./module.js').then(module=>{
        module.fn()
    })
}

Bigint

//大整形
let n = 520n
//函数
console.log(Bigint(123))//123n  浮点型不行
//大数值运算  Bigint不能直接与一般数值进行运算,需要对一般数值进行Bigint转换

绝对全局对象

golbalThis