es6学习笔记

199 阅读17分钟

1 es6新特性

1.1 let 关键字

let 关键字用来声明变量,使用 let 声明的变量有几个特点:

  1. 不允许重复声明
  2. 块儿级作用域
  3. 不存在变量提升
  4. 不影响作用域链

应用场景:以后声明变量使用 let 就对了

1.2 const关键字

const关键字用来声明常量,const声明有以下特点

  1. 声明必须赋初始值
  2. 标识符一般为大写
  3. 不允许重复声明
  4. 值不允许修改
  5. 块儿级作用域
  6. 注意:对象属性修改和数组元素变化不会触发const错误,因为地址没有改变

应用场景:声明对象类型使用const,非对象类型声明选择let

1.3 变量的解构赋值

image-20220526093415577.png

image-20220526093449711.png

1.4 模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:

  1. 字符串中可以出现换行符
  2. 可以使用 ${xxx} 形式输出变量

1.5 简化对象写法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

let zh = {
            // improve: function(){
            //     console.log(111);
            // }
            // 简写形式
            improve(){
                console.log(111);
            }
        }

1.6 箭头函数

ES6 允许使用「箭头」(=>)定义函数。

箭头函数的注意点:

  1. 如果形参只有一个,则小括号可以省略

  2. 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果,return必须省略

  3. 箭头函数 this 指向声明时所在作用域下 this 的值,并且this是静态的,调用call方法也不能改变

            let jian1 = function(){
                console.log(this.name);
            }
            let jian2 = () => {
                console.log(this.name);
            }
            let school = {
                name: '前台',
            }
            window.name = '尚硅谷'
            jian1()
            jian2()
            console.log('==================');
            jian1.call(school) // 前台
            jian2.call(school) //依然是尚硅谷
    
  4. 箭头函数不能作为构造器,构造函数,来实例化对象

    let hh = (name, age) => {
                this.name = name,
                this.age = age
            }
            let zs = new hh() //会报错
    
  5. 不能使用 arguments

        let zhao = () => {
            console.log(arguments);// 报错,argument is not defined
        }
        zhao()

1.7 函数参数的默认值设置

1.允许给函数参数赋予默认初始值,并且通常放在后面

function ff(a, b, c=10){
            return a + b + c
        }
        console.log(ff(1, 5));

2.与解构赋值结合使用

function ff({a, b, c=10}){
            return a + b + c
        }
console.log(ff({a: 1, b: 5}));

1.8 rest参数

ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments,rest参数必须放到最后

function hu(){
            console.log(arguments);
        }
function zh(...args){
            console.log(args);
        }
hu(1,2,3,5,9) //对象
zh(1,2,3,5,9) //数组

1.9 扩展运算符

扩展运算符(spread)也是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。

1. 数组的合并
let a = ['zas', 'kjkj','kjkkas']
console.log(...a); // 结果 zas kjkj kjkkas
let b = ['咋还不干', '杂技']
let c = b.concat(a) // 
let d = [...a, ...b]
console.log(c); // ['咋还不干', '杂技', 'zas', 'kjkj', 'kjkkas']
console.log(d); // ['zas', 'kjkj', 'kjkkas', '咋还不干', '杂技']2. 数组拷贝 // 浅拷贝
let e = [...a]
console.log(e); //['zas', 'kjkj', 'kjkkas']3. 将伪数组转为真正的数组

1.10 第七种数据类型symbol

八种数据类型:usonb(you are so nb) {undefined, string, symbol, object, number , null, boolean, bigint} ,NaN属于Number类型

ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。

Symbol 特点

  1. Symbol 的值是唯一的,用来解决命名冲突的问题
  2. Symbol 值不能与其他数据进行运算
  3. Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用Reflect.ownKeys 来获取对象的所有键名
let s = Symbol()
console.log(s, typeof s); // Symbol() 'symbol'
let s1 = Symbol('尚硅谷')
let s2 = Symbol('尚硅谷')
console.log(s1 === s2, s1); // false Symbol(尚硅谷)
let s3 = Symbol.for('山硅')
let s4 = Symbol.for('山硅')
// 不能与其他数据进行运算
console.log(s3 === s4, s3) // true Symbol(山硅)
s3 + 10 //报错

应用场景

// 向对象中添加方法
        let school = {
            up(){
                console.log(111);
            },
            down(){
                console.log(222);
            }
        }
        // 第一种方式,声明一个对象
        let set = {
            up: Symbol(),
            down: Symbol()
        }
        school[set.up] = function(){
            console.log(1111);
        }
        school[set.down] = function(){
            console.log(2222);
        }
        console.log(school); //up: ƒ, down: ƒ, Symbol(): ƒ, Symbol(): ƒ}
        // 第二种方式,直接用
        let ss = {
            name: 'as',
            [Symbol('say')](){
                console.log(111);
            },
            [Symbol('sy')](){
                console.log(111);
            }
        }
        console.log(ss); // {name: 'as', Symbol(say): ƒ, Symbol(sy): ƒ}

symbol 的内置属性

        class Person {
            static [Symbol.hasInstance](params){
                console.log(params);
                return false
            }
        }
        let o = {}
        console.log(o instanceof Person); // {} // false

        const arr1 = [1,2,3]
        const arr2 = [1,2,3]
        
        arr2[Symbol.isConcatSpreadable] = false
        console.log(arr2.concat(arr1)); //[Array(3), 1, 2, 3] 

1.11 迭代器

迭代器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。

  1. ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费

  2. 原生具备 iterator 接口的数据(可用 for of 遍历)

    1. Array
    2. Arguments
    3. Set
    4. Map
    5. String
    6. TypedArray
    7. NodeList

工作原理

  1. 创建一个指针对象,指向当前数据结构的起始位置
  2. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
  3. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
  4. 每调用 next 方法返回一个包含 value 和 done 属性的对象
        let arr = ['唐山', '按时', '不信', '回家']
        for (const i in arr) {
            console.log(i);  // 0,1,2,3 输出的是索引
            }
        for (const i of arr) {
        console.log(i);  // '唐山', '按时', '不信', '回家'
        }
let iterator = arr[Symbol.iterator]()
console.log(iterator.next()); //{value: '唐山', done: false}

需要自定义遍历数据的时候,要想到迭代器。

// 自定义迭代器
        let arr = ['唐山', '按时', '不信', '回家'];
        let school = {
            name: '上回顾',
            people: arr,
            [Symbol.iterator]: function(){
                let index = 0;
                let that = this;
                return {
                    next(){
                        if(index < that.people.length){
                            let result = {value: that.people[index], done: false}
                            index++
                            return result
                        }else{
                            return {value: undefined, done: true}
                        }  
                    }
                }
            }
        }
        for (let i of school) {
            console.log(i);
        }

1.12 生成器函数

生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同

function * hhh(){
            console.log(111);
            yield 'qqqq',
            console.log(222);
            yield 'bbbb',
            console.log(333);
            yield 'cccc',
            console.log(444);
            yield 'ffff',
            console.log(5555);
        }
        // 生成器函数调用不会直接执行,需要调用next()函数才会执行,并且,一次next()只会执行一段yield区域
        let iterator = hhh()

        iterator.next(); // 111
        iterator.next(); // 222
        iterator.next(); // 333
        iterator.next(); // 444
        
        console.log(iterator.next()); // {value: 'qqqq', done: false}
        console.log(iterator.next()); // {value: 'bbbb', done: false}

// 生成器函数传参
        function * hhh(aaa){
            console.log(aaa);
            let a1 = yield 'qqqq';
            console.log(a1);
            let a2 = yield 'bbbb';
            console.log(a2);
            let a3 = yield 'cccc';
            console.log(a3);
        }
        let iterator = hhh('尚硅谷')
        console.log(iterator.next('顺一块')) //尚硅谷 //{value: 'qqqq', done: false}
        console.log(iterator.next('顺二块')) //顺二块 //{value: 'bbbb', done: false}
        console.log(iterator.next('顺三块')) //顺三块 //{value: 'cccc', done: false}
        console.log(iterator.next('顺四块')) //顺四块 //{value: undefined, done: true}
// 第二次next()传递的参数,作为第一个yield的返回结果

代码说明:

  1. *的位置没有限制
  2. 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到yield 语句后的值
  3. yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码
  4. next 方法可以传递实参,作为 yield 语句的返回值
// 回调地狱问题
        setTimeout(() => {
            console.log(111);
            setTimeout(() => {
                console.log(222);
                setTimeout(() => {
                    console.log(333);
                }, 3000)
            }, 2000)
        }, 1000)
 // 生成器函数解决方案
        function one(){
            setTimeout(()=>{
                console.log(111);
                iterator.next()
            }, 1000)
        }
        function two(){
            setTimeout(()=>{
                console.log(222);
                iterator.next()
            }, 2000)
        }
        function three(){
            setTimeout(()=>{
                console.log(333);
                iterator.next()
            }, 3000)
        }
        function * hhh(){
            yield one()
            yield two()
            yield three()
        }
        let iterator = hhh()
        iterator.next()
// 生成器函数在异步任务中的应用
        function getUsers(){
            setTimeout(()=>{
                let data = '用户信息';
                iterator.next(data)
            },1000)
        }
        function getOrders(){
            setTimeout(()=>{
                let data = '订单数据';
                iterator.next(data)
            },1000)
        }
        function getGoods(){
            setTimeout(()=>{
                let data = '商品数据';
                iterator.next(data)
            },1000)
        }
        function * Gen(){
            let a = yield getUsers()
            console.log(a);
            let b = yield getOrders()
            console.log(b);
            let c = yield getGoods()
            console.log(c);
        }
        let iterator = Gen()
        iterator.next()

1.13 promise

Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,

  1. 用来封装异步操作并可以获取其成功或失败的结果。
  2. Promise 构造函数: Promise (excutor) {}
  3. Promise.prototype.then 方法
  4. Promise.prototype.catch 方法
// promise的基本使用
let p = new Promise(function(resolve, reject){
            setTimeout(()=>{
                let data = '安徽是个好地方'
                // resolve(data)
                reject(data)
            },1000)
        })
// 当回调函数调用resolve,则then中执行第一个函数,reject则执行第二个函数
        p.then(function(value){
            console.log(value); 
        },function(reason){
            console.error(reason);
        })
// promise读取文件操作
// 正常方式
const fs = require('fs')
fs.readFile('../ES6/ES6_Promise/resources/为学.md', (err, res)=>{
    if(err) {throw err}else{
        console.log(res.toString());
    }
})
// promise风格的写法
const p = new Promise(function(resolve, reject){
    fs.readFile('../ES6/ES6_Promise/resources/为学.md2', (err, res)=>{
        if(err){
            reject(err)
        }else{
            resolve(res)
        }
    })
})
p.then(function(valve){
    console.log(valve.toString());
}, function(reason){
    console.log(reason);
})
// promise封装AJAX请求
// 原生xhr发起请求
        const xhr = new XMLHttpRequest()
        xhr.open('GET', 'https://api.apiopen.top/getJoke');
        xhr.send()
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    console.log(xhr.response);
                } else {
                    console.log(xhr.status);
                    console.log('0000');
                }
            }
        }

// promise风格发起请求
        const p = new Promise(function (resolve, reject) {
            const xhr = new XMLHttpRequest()
            xhr.open("GET", "https://api.apiopen.top/getJoke");
            xhr.send()
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        resolve(xhr.response);
                    } else {
                        reject(xhr);
                    }
                }
            }
        })
        p.then(function(value){
            console.log(value);
        }, function(reason){
            console.log(reason);
        })
// promise对象的返回结果
const p = new Promise(function (resolve, reject) {
            setTimeout(() => {
                let data = '转啊看见了'
                // resolve(data)
                reject(data)
            }, 1000)
        })
        const result = p.then((value) => {
            console.log(value);
        },
            (reason) => {
                console.warn(reason);
            })
        console.log(result);
        // then()的返回结果任然是promise对象,且返回对象的状态取决于then()中定义的函数的返回结果,
        // 1. 如果返回结果为非promise对象,则result的状态为resolved(成功),且返回值为对象的成功值
        // 2. 如果返回结果是promise对象,则返回的promise对象的状态即为result的状态(见result2的返回结果)
        // 3. 如果返回结果是抛出错误,则返回结果的状态为失败,值为error的内容
        const result1 = p.then((value) => {
            console.log(value);
            return '1111'
        }, (reason) => {
            console.warn(reason);
        })
        console.log(result1); // 返回值状态为成功,成功值为111

        const result2 = p.then((value) => {
            console.log(value);
            return new Promise(function(resolve, reject){
                resolve('data') // result2的状态为成功, 值为data
                reject('data') // result2的状态为失败, 值为data
            })
        }, (reason) => {
            console.warn(reason);
        })
        console.log(result1); 

        const result3 = p.then((value) => {
            console.log(value);
            throw 'error'
        }, (reason) => {
            console.warn(reason);
        })
        console.log(result1); // 返回值状态为失败,值为error

        // 因此,then()方法可以链式调用,里面的函数也可以只写成功的回调
        p.then(value => {}).then(value => {})
// 回调地狱小案例
const fs = require('fs')
// 回调地狱的一个问题就是变量名容易重复,且不易发现
fs.readFile('../ES6/ES6_Promise/resources/为学.md',(err, res1)=>{
    fs.readFile('../ES6/ES6_Promise/resources/插秧诗.md',(err, res2)=>{
        fs.readFile('../ES6/ES6_Promise/resources/观书有感.md',(err, res3)=>{
            let data = res1 + '\n' + res2 + '\n' + res3
            console.log(data);
        })
    })
})

const p1 = new Promise(function(resolve, reject){
    fs.readFile('../ES6/ES6_Promise/resources/为学.md',(err, res1)=>{
        resolve(res1)
    })
})
p1.then((value)=>{
    return new Promise(function(resolve, reject){
        fs.readFile('../ES6/ES6_Promise/resources/插秧诗.md',(err, res1)=>{
            resolve(res1 + '\n' + value)
        })
    })
}).then((value) =>{
    return new Promise(function(resolve, reject){
        fs.readFile('../ES6/ES6_Promise/resources/观书有感.md',(err, res1)=>{
            resolve(res1 + '\n' + value)
        })
    })
}).then((value)=> {
    console.log(value);
})

promise的catch()方法

const p = new Promise(function(resolve, reject){
    fs.readFile('../ES6/ES6_Promise/resources/为学.md2', (err, res)=>{
        if(err){
            reject(err)
        }else{
            resolve(res)
        }
    })
})
// catch()只需要配置一个错误的函数即可
p.catch((error)=>{
    console.log(error);
})

1.14 集合set(本质上也是对象)

ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:

  1. size 返回集合的元素个数
  2. add 增加一个新元素,返回当前集合
  3. delete 删除元素,返回 boolean 值
  4. has 检测集合中是否包含某个元素,返回 boolean 值
  5. clear 清空集合,返回 undefined
        let s = new Set(['爱上了肯德基', '奥斯卡缴费', '萨科技', '奥斯卡缴费'])
        console.log(s); // {'爱上了肯德基', '奥斯卡缴费', '萨科技'}
        // 集合的方法
        console.log(s.size);
        s.add('阿萨德')
        console.log(s); // {'爱上了肯德基', '奥斯卡缴费', '萨科技', '阿萨德'}
        s.delete('爱上了肯德基')
        console.log(s); // {'奥斯卡缴费', '萨科技', '阿萨德'}
        // s.clear() // 清空集合
        console.log(s.has('阿萨德'));
        for(let v of s){
            console.log(v);
        }
        console.log(...s);
        
	// set实践
        let s = [1, 3 , 7, 8, 2, 1, 3]
        // 数组去重
        let s1 = [...new Set(s)]
        console.log(s1);
        // 交集
        let arr = [8, 2, 1, 3, 5, 42, 86, 96]
        let s2 = [...new Set(s)].filter((item)=>new Set(arr).has(item))
        console.log(s2);
        // 并集
        let s3 = [...new Set([...s, ...arr])]
        console.log(s3);
        // 差集
        let s4 = [...new Set(s)].filter(item=>!((new Set(arr)).has(item)))
        console.log(s4);

1.15 Map

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map 的属性和方法:

  1. size 返回 Map 的元素个数
  2. set 增加一个新元素,返回当前 Map
  3. get 返回键名对象的键值
  4. has 检测 Map 中是否包含某个元素,返回 boolean 值
  5. clear 清空集合,返回 undefined
        let a = new Map()
        // 添加元素
        a.set('name', '尚硅谷')
        let b = {
            name: '尚硅谷'
        }
        a.set(b, ['as', 'wjqd', 'qcs'])
        console.log(a);
        // size
        console.log(a.size);
        // 删除
        // a.delete('name')
        // console.log(a);
        // 读取
        console.log(a.get(b));
        // 清空
        // a.clear()
        // 遍历
        for(v of a){
            console.log(v); // 遍历的结果是数组
        }

1.16 class类

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

1. 知识点:

  1. class 声明类
  2. constructor 定义构造函数初始化
  3. extends 继承父类
  4. super 调用父级构造方法
  5. static 定义静态方法和属性
  6. 父类方法可以重写
        // es5写法
        function Phone(name, price) {
            this.name = name
            this.price = price
        }
        Phone.prototype.call = function () {
            console.log('woshishouji');
        }
        let huawei = new Phone('huawei', 19)
        console.log(huawei);
        huawei.call()
        // es6写法
        class ShouJi {
            constructor(name, price) {
                this.name = name
                this.price = price
            }
            call(){
                console.log('woshishouji');
            }
        }
        let huawei1 = new Phone('huawei', 19)
        console.log(huawei);
        huawei.call()

2.函数对象的属性和实例对象的属性是不相通的,实例对象和函数对象的原型对象是通的

        function Phone() {
        }
        Phone.prototype.call = function () {
            console.log('woshishouji');
        }
        Phone.name = 'zd' // 相当于类的静态成员
        let nokia = new Phone()
        console.log(nokia.name); // undefined
        nokia.call() 
        // es6静态成员写法
 class Phone{
            // 静态成员
            static name = 'as'
            static ff(){
                console.log('5adss');
            }
        }
        let nokia = new Phone 
        console.log(nokia.name); // undefined
        nokia.ff()// 未定义

3.继承与方法重写

// es5中的继承
		function Phone(name, price) {
            this.name = name
            this.price = price
        }
        function SmartPhone(name, price ,color, size){
            Phone.call(this, name, price)
            this.color = color
            this.size = size

        }
        Phone.prototype.dial = function(){
            console.log('我可以打电话');
        }
        // 设置子集构造函数的原型
        SmartPhone.prototype = new Phone
        SmartPhone.prototype.constructor = SmartPhone
        SmartPhone.prototype.phote = function(){
            console.log('我可以拍照');
        }
        let chuizi = new SmartPhone('chuizi', 2555, '黑色', '5.5')
        console.log(chuizi);
// es6 中的继承
        class Phone{
            constructor(name, price){
                this.name = name
                this.price = price
            }
            dial(){
                console.log('我可以打电话')
            }
        }
        class SmartPhone extends Phone{
            constructor(name, price ,color, size){
                super(name, price)
                this.color = color
                this.size = size
            }
            photo(){
                console.log('我可以拍照');
            }
            // 方法重写,但是不可以调用父类中的方法
            dial(){
                super() // 会报错
                console.log('我可以视频通话');
            }
        }
        let xio = new SmartPhone('chuizi', 2555, '黑色', '5.5')
        console.log(xio);

4.class的set()和get()

		   get name1(){
                console.log('get调用了');
                return this.name}
            set name1(val){
                console.log('get调用了');
                return this.name}

1.17 ES6的数值扩展

        // Number.EPSILON
        function equal(a, b){
            if(Math.abs(a - b) < Number.EPSILON){return true}else{return false}
        }
        console.log(0.1 + 0.2 === 0.3);
        console.log(equal(0.1 + 0.2, 0.3));
        // 二进制、八进制、十进制、十六进制
        let b = 0b1010 // 10
        let o = 0o777 // 511
        let d = 100 // 100
        let x = 0xff // 255
        // Number.isFinite() 判断一个数是否是有限的
        console.log(Number.isFinite(NaN)); // false
        console.log(Number.isFinite(Infinity)); // false
        // Number.isNaN() 判断一个数是否为NaN
        console.log(Number.isNaN(NaN)); // true
        console.log(Number.isNaN(Infinity)); // false
        console.log('----------------');
        // Number.parseInt(),Number.parseFloat() 字符串转换为整数,浮点数
        console.log(Number.parseFloat('0.355as')); // 0.355
        console.log(Number.parseInt('355as'));// 355
        // Number.isInteger() 判断一个数是否为整数
        console.log(Number.isInteger(2.5));// false
        // Math.trunc() 将数字的小数部分抹掉
        console.log(Math.trunc(3.6));// 3
        // Math.sign() 判断一个数到底是正数负数还是0
        console.log(Math.sign(100));// 1
        console.log(Math.sign(-100));// -1
        console.log(Math.sign(0));// 0

1.18 对象方法扩展

		// Object.is() 判断两个值是否相等,和===相似,但有区别
        console.log(Object.is(NaN, NaN)); //true
        console.log(NaN === NaN);//false
        // Object.assign() 将两个对象合并,前者的属性会被后者所覆盖,新的对象会包括两者的所有属性
        let a = {
            name: '阿萨德',
            age: 15,
            text: 111
        }
        let b = {
            name: '阿萨德前端',
            age: 56,
            test: 22828
        }
        // console.log(Object.assign(a, b)); 
        // Object.setPrototypeOf(),Object.getPrototypeOf() 设置和得到一个对象的原型对象,可以但不推荐这样去做
        Object.setPrototypeOf(a, b) // 设置a的原型对象为b
        console.log(a);

1.19 es6 模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

模块化的好处

  1. 防止命名冲突
  2. 代码复用
  3. 高维护性

模块化规范产品

ES6 之前的模块化规范有:

  1. CommonJS => NodeJS、Browserify
  2. AMD => requireJS
  3. CMD => seaJS
// export部分
// 分别暴露
export let a = '萨那点钱'
export function oo(){
    console.log('我是模块化');
}
// import部分
	<script type="module">
        import * as m1 from './26es6模块化.js'
        console.log(m1.a);
    </script>

// 统一暴露
// export部分
let a = '萨那点钱'
function oo(){
        console.log('我是模块化');
    }
export {a, oo}
// import部分
	<script type="module">
        import * as m1 from './26es6模块化.js'
        console.log(m1.a);
    </script>

// 默认暴露
// export部分
export default {
    name: 'asad',
    inje(){
        console.log('lkjdsh');
    }
}
// import部分 
<script type="module">
        import * as m1 from './26es6模块化.js'
        console.log(m1.default.name); // 需要加一层default
        m1.default.inje()
</script>

模块导入方法汇总

        // 模块导入方法汇总
        // 通用的引入方式
        import * as m1 from './26es6模块化.js'
        console.log(m1.default.name);
        m1.default.inje()
        // 解构赋值的形式
        import {default as m1} from './26es6模块化.js'
        import {a, oo} from './26es6模块化.js'
        import {a as pp, oo} from './26es6模块化.js'
        // 简便形式,只适用于默认暴露
        import m1 from './26es6模块化.js'

模块化使用的另外一种方式

// 在app.js中
import * as m1 from './26es6模块化.js'
console.log(m1.a);
// 在index.html中
<script src="./27app.js" type="module"></script>

babel对es6语法进行转化

        1. 安装工具 npm i babel-cli babel-preset-env browserify(webpack) -D
        2. 编译 npx babel src/js -d dist/js --presets=babel-preset-env
        3. 打包 npx browserify dist/js/app.js -o dist/bundle.js

2 es7新特性

        // Array.prototype.incudes()方法,有返回true,没有返回false
        let arr = [1, 6, 8, 6]
        console.log(arr.includes(8));
        // ** 运算符,和Math.pow()的作用相似
        console.log(2 ** 5);

3 es8新特性

3.1 async函数和await表达式

// async函数返回的结果都是promise对象,其结果由return值决定
        async function fn(){
            // 这里返回的结果,和then()方法结果一样,如果是非promise对象,如字符串,数组等等,返回的promise对象状态为fulfilled,值为return 的值
            // return '安徽'
            // 抛出错误返回结果是fulfilled,值是return的值
            // return new Error('kkk')
            // 如果返回结果是promise对象,则由这个promise对象决定函数执行结果
            return new Promise((resolve, reject)=>{
                reject(111)
            })
        }
        let temp = fn()
        console.log(temp);
        // await表达式
        let p = new Promise((resolve,reject)=>{
            resolve('用户数据')
        })
        async function fn(){
            try{
                let result = await p; // 通常在await后面放一个promise表达式,其返回结果就是promise成功的值
                console.log(result);
            }catch(e){
                console.log(e);
            }
        }
        fn()

await表达式

  1. await 必须写在 async 函数中
  2. await 右侧的表达式一般为 promise 对象
  3. await 返回的是 promise 成功的值
  4. await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理

读取文件案例(结合起来使得代码非常像同步编程)

const fs = require('fs')
function read1(){
    return new Promise((resolve, reject)=>{
        fs.readFile('../ES6/ES6_Promise/resources/为学.md',(err,res)=>{
            if(err) return reject(err)
            resolve(res)
        })
    })
}
function read2(){
    return new Promise((resolve, reject)=>{
        fs.readFile('../ES6/ES6_Promise/resources/插秧诗.md',(err,res)=>{
            if(err) return reject(err)
            resolve(res)
        })
    })
}
function read3(){
    return new Promise((resolve, reject)=>{
        fs.readFile('../ES6/ES6_Promise/resources/观书有感.md',(err,res)=>{
            if(err) return reject(err)
            resolve(res)
        })
    })
}
async function main(){
    let read11 = await read1()
    let read12 = await read2()
    let read13 = await read3()
    console.log(read11.toString());
    console.log(read12.toString());
    console.log(read13.toString());
}
main()

发送Ajax案例

        function sendAJAX(url) {
            return new Promise((resolve, reject) => {
                const xml = new XMLHttpRequest()
                xml.open('GET', url)
                xml.send()
                xml.onreadystatechange = function () {
                    if (xml.readyState === 4) {
                        if (xml.status >= 200 && xml.status < 300) {
                            resolve(xml.response)
                        }else(reject(xml.status))
                    }
                }
            })
        }
        // Promise.then()方法的测试
        // sendAJAX('https://api.uomg.com/api/rand.qinghua').then((value)=>{
        //     console.log(value);
        // },(reason)=>{
        //     console.log(reason);
        // })

        // async函数实现
        async function main(){
            let result = await sendAJAX('https://api.uomg.com/api/rand.qinghua')
            console.log(result);
        }
        main()

3.2 对象方法扩展

  1. Object.values()和 Object.entries()

    1. Object.values()方法返回一个给定对象的所有可枚举属性值的数组(对应还有一个Object.keys()方法获取所有的键名)
    2. Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组
  2. Object.getOwnPropertyDescriptors() 该方法返回指定对象所有自身属性的描述对象

        let school = {
            name: '尚硅谷',
            citys: ['背', '上', '广'],
            subject: ['咋混', '找我', '按时']
        }
        // Object.values()
        console.log(Object.keys(school));
        console.log(Object.values(school));
        // Object.entries(),方便创建Map
        console.log(Object.entries(school));
        const m = new Map(Object.entries(school))
        console.log(m.get('citys'));
        // 对象所有自身属性的描述对象
        console.log(Object.getOwnPropertyDescriptor(school));
        // 返回结果见图

image-20220527171715450.png

4 es9新特性

4.1 扩展运算符与rest参数

        let school = {
            name: '尚硅谷',
            citys: ['背', '上', '广'],
            subject: ['咋混', '找我', '按时']
        }
        let school2 = {
            name: '黑马',
            citys: ['背', '上', '广'],
            like: '阿卡去'
        }
        function ff({name, ...rest}){
            console.log(name);
            console.log(rest);
        }
        ff(school) 
        let ooo = {...school, ...school2}
        console.log(ooo); // {name: '黑马', citys: Array(3), subject: Array(3), like: '阿卡去'}

4.2 正则扩展

4.2.1 命名捕获分组

        // ?<name> 
        let a = '<a href="https://www.baidu.com">尚硅谷</a>'
        const reg = /<a href="(?<url>.*)">(?<text>.*)</a>/
        let res = reg.exec(a)
        console.log(res);
        console.log(res.groups);

输出结果:

image-20220527174732885.png

4.2.2 反向断言

        let a = 'js546466阿萨德刚654489阿布'
        // 正向断言
        const reg = /\d+(?=阿布)/
        let res = reg.exec(a)
        // 反向断言
        const reg2 = /(?<=德刚)\d+/
        let res2 = reg2.exec(a)
        console.log(res);
        console.log(res2);

4.2.3 dotall模式

//dot  .  元字符  除换行符以外的任意单个字符
let str = `
        <ul>
            <li>
                <a>肖生克的救赎</a>
                <p>上映日期: 1994-09-10</p>
            </li>
            <li>
                <a>阿甘正传</a>
                <p>上映日期: 1994-07-06</p>
            </li>
        </ul>`;
        // 没有dotall情况下
        const reg = /<li>\s+<a>(.*?)</a>\s+<p>(.*?)</p>/
        let res = reg.exec(str)
        // 有dotall情况下
        const reg2 = /<li>.*?<a>(.*?)</a>.*?<p>(.*?)</p>/s
        let res2 = reg2.exec(str)
        console.log(res);
        console.log(res2);
        // 全局匹配
        let data = []
        const reg3 = /<li>.*?<a>(.*?)</a>.*?<p>(.*?)</p>/gs
        let res3;
        while(res3= reg3.exec(str)){
            data.push({title: res3[1], time: res[2]})
        }
        console.log(data);

5 es10新特性

5.1 Object.fromEntries()

        // 二维数组 将二维数组转化为对象
        const res = Object.fromEntries([['name','尚硅谷'],['aasd', '爱上规划']])
        console.log(res);
        // Map 将map转化为对象
        const m = new Map()
        m.set('name', '尚硅谷')
        const res2 = Object.fromEntries(m)
        console.log(res2);
        // entries与fromEntries的作用正好相反,将对象转换成数组
        const e = Object.entries({name:'尚硅谷'})
        console.log(e);

5.2 Str.trimStart()方法和Str.trimEnd()方法分别去除字符串左边和右边的空白

// Str.trimStart()方法和Str.trimEnd()方法分别去除字符串左边和右边的空白        
let str = '    asd  '
        console.log(str.trimStart());
        console.log(str.trimEnd());

5.3 flat()方法和flatMap()方法

        // flat将多维数组转化为低维数组,传递的参数为降低的维数,默认是1
        let str = [2, 5, 6, 5, [6, 654, 58, [6, 4]]]
        console.log(str.flat()); // [2, 5, 6, 5, 6, 654, 58, Array(2)]
        console.log(str.flat(2)); // [2, 5, 6, 5, 6, 654, 58, 6, 4]
        // flatMap()方法
        const arr1 = [2, 5, 6, 5]
        res = arr1.map((item)=>item * 10) 
        res1 = arr1.map((item)=>[item * 10]) 
        res2 = arr1.flatMap((item)=>[item * 10]) 
        console.log(res); //[20, 50, 60, 50] 
        console.log(res1); // [Array(1), Array(1), Array(1), Array(1)]
        console.log(res2); // [20, 50, 60, 50]

5.4 Symbol.prototype.destription属性

        let s = Symbol('山硅阿萨德')
        console.log(s.description); // 山硅阿萨德

6 es11新特性

6.1 私有属性

        class Person{
            name
            // 私有属性以#开头, 外部无法直接获取
            #age
            constructor(name, age){
                this.name = name
                this.#age = age
            }
            intro(){
                console.log(this.name);
                console.log(this.#age);
            }
        }
        let i = new Person('安徽省级', 18)
        console.log(i.#age); // 报错
        i.intro()

6.2 Promise的allSettled()方法

        const p1 = new Promise((resolve, reject)=>{
            reject('商品属性-1')
        })
        const p2 = new Promise((resolve, reject)=>{
            reject('商品属性-2')
        })
        // 两个方法传入的参数都为数组
        // all方法的返回结果,当两个promise对象的结果都为true时为true,否则为false,返回的结果是异步任务失败的值
        // allSettled()方法返回的结果无论如何都为true,返回的结果是异步任务的结果
        // 用于执行批量异步任务
        const res1 = Promise.all([p1,p2])
        const res2 = Promise.allSettled([p1,p2])
        console.log(res1);
        console.log(res2);

6.3 String.prototype.matchAll()方法

        let str = `
        <ul>
            <li>
                <a>肖生克的救赎</a>
                <p>上映日期: 1994-09-10</p>
            </li>
            <li>
                <a>阿甘正传</a>
                <p>上映日期: 1994-07-06</p>
            </li>
        </ul>`;
        const reg2 = /<li>.*?<a>(.*?)</a>.*?<p>(.*?)</p>/gs
        // matchAll()方法匹配结果是一个可迭代数组
        const res = str.matchAll(reg2)
        for (v of res){
            console.log(v);
        }
        console.log([...res]);

6.4 可选链操作符(?.)

        function fn(config){
            // 没有可选链操作符,需要一级一级判断,否则若没有传参,会报错
            // const dbhost = config && config.db && config.db.host
            // 有可选链操作符
            const dbhost = config?.db?.host
            console.log(dbhost);
        }
        fn({
            db: {
                host: '165246.596.56',
                wd: 56464
            },
            fva: {
                host: '165.596.56',
                wd: '56q8w4'
            }
        })

6.5 动态import语句

        const ff = document.querySelector('.btn')
        ff.onclick = function(){
            // 动态引入返回结果是一个promise对象
            import('./46hello.js').then((modules)=>{
                modules.hello()
            })
        }

6.6 BigInt类型

        // 大整型 只要在整数后面加个n
        let n = 524n
        console.log(n, typeof(n)); // 524n 'bigint'
        // 函数
        let m = BigInt(521)
        let k = BigInt(5.21) 
        console.log(m); // 521n
        console.log(k); 报错
        let max = Number.MAX_SAFE_INTEGER
        console.log(max); // 9007199254740991
        console.log(max + 1);// 9007199254740992
        console.log(max + 2);// 9007199254740992
        console.log(BigInt(max));// 9007199254740991n
        console.log(BigInt(max) + BigInt(1));// 9007199254740992n
        console.log(BigInt(max) + BigInt(2));// 9007199254740993n

6.7 globalThis绝对全局对象

console.log(globalThis); // 指向window对象
// nodejs环境下,指向global对象

\