ES6 - ES11新特性

186 阅读27分钟

第 1章、 ECMASript 相关介绍

1.1什么是ECMA

image-20220408205106928.png

ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1994 年后该组织改名为 Ecma 国际。

1.2 什么是 ECMAScript

ECMAScript 是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言

1.3 什么是 ECMA-262

Ecma 国际制定了许多标准,而 ECMA-262 只是其中的一个,所有标准列表查看

www.ecma-international.org/publication…

1.4ECMA-262历史

ECMA-262(ECMAScript)历史版本查看网址

www.ecma-international.org/publication…

第 1 版1997 年制定了语言的基本语法
第 2 版1998 年较小改动
第 3 版1999 年引入正则、异常处理、格 式化输出等。IE 开始支持
第 4 版2007 年过于激进,未发布
第 5 版2009 年引入严格模式、JSON,扩展对象、数组、原型、字 符串、日期方法
62015模块化、面向对象语法、 Promise、箭头函数、let、 const、数组解构赋值等等
第 7 版2016 年幂运算符、数组扩展、 Async/await 关键字
第 8 版2017 年Async/await、字符串扩展
第 9 版2018 年对象解构赋值、正则扩展
第 10 版2019 年扩展对象、数组方法
ES.next动态指向下一个版本

注:从 ES6 开始,每年发布一个版本,版本号比年份最后一位大 1

1.5谁在维护ECMA-262

TC39(Technical Committee 39)是推进 ECMAScript 发展的委员会。其会员都是公司(其中主要是浏览器厂商,有苹果、谷歌、微软、因特尔等)。TC39 定期召开会议,会议由会员公司的代表与特邀专家出席

1.6为什么使用ES6

  • ES6 的版本变动内容最多,具有里程碑意义
  • ES6 加入许多新的语法特性,编程实现更简单、高效
  • ES6 是前端发展趋势,就业必备技能

1.7 ES6 兼容性

kangax.github.io/compat-tabl… 可查看兼容性

image-20220408153152937.png

第二章、ECMASript6的新特性

2.1 let关键字

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

  1. 不允许重复声明
    let a = "张三";
    let a = "男"  // 会报错 Identifier 'a' has already been declared 
  1. 块儿级作用域(if、else、while、 for在这些中都会有块级作用域)
       if(true){
            // let a = "张三";
            var a = "张三";
        }
        console.log(a); // 报错  a is not defined 
        console.log(a); //张三  var没有块级作用域
  1. 不存在变量提升
       console.log(a);
       let a = "张三";  //会报错 Cannot access 'a' before initialization
​
       console.log(b);  //undefined  var会变量提升
       var b = "李四"; 
  1. 不影响作用域链
  function fun(){
            let a = "张三";
            function fun1(){
                console.log(a);
            }
            fun1()
        }
​
        fun() //张三

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

2.1.1 点击切换颜色
//需要给div添加样式
<div class="yhl">
        <h2 class="ll">点击切换颜色</h2>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
​
    <script>
        // 获取元素
        let items = document.getElementsByClassName("item");
        // 循环遍历
        for (let  i = 0; i < items.length; i++) {
            //绑定点击事件
            items[i].onclick = function () {
                console.log(i);
                // 如果用var下面这样写就不行 因为i = 3 我们就定义三个索引最大为2 所以会报错
                // 为什么会变成3呢 因为var i是一个全局变量 i一直在自增 所以i出循环以后就是3了
                // 怎么解决  把for循环的var换成let 就可以完美解决了
                items[i].style.background = 'pink';
            }
        }
    </script>

2.2.const关键字

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

  1. 声明必须赋初始值
         // 声明必须赋初始值
         const A; //会报错,所以声明变量的时候要复制
  1. 标识符一般为大写(潜规则)
        // 标识符一般为大写(潜规则)
         const a = 10;
         console.log(a); //10
  1. 不允许重复声明
        //  不允许重复声明
        const A = "张三";
        const A = "李四"; //报错
  1. 值不允许修改
         // 值不允许修改
        const A = "张三";
        A = "李四"; //报错 常量不能改
  1. 块儿级作用域
         // 块级作用域
        if(true){
          let A = "张三";
         }
         console.log(A); //报错

注意 :  对象属性修改和数组元素变化不会出发 const 错误

       //对象数组可以修改
        const A = [1,2,3,4]; 
        A.push(5)
        console.log(A);  //[1,2,3,4,5]

常量的值不是不可以改变吗,这个为什么可以改?

因为数组和对象的所指向的地址没有改变,所以不会报错

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

2.3变量的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。

数组的解构赋值

        // 数组的变量解构赋值
        let arr = ["赵本山", "小沈阳", "丫蛋", "刘能"];
        let [zhao, xiao, ya, liu] = arr;
        console.log(zhao); // 赵本山
        console.log(xiao); // 小沈阳
        console.log(ya);   // 丫蛋
        console.log(liu);  // 刘能

简单对象的解构赋值

   const obj = {
            name: "赵本山",
            age: 80,
            say: function () {
                console.log("我可以演小品");
            }
        }
​
        const { name, age, say } = obj;
        console.log(name); //赵本山
        console.log(age); // 80
        console.log(say); //function(){console.log("我可以演小品")}

复杂对象的解构赋值

       let obj = {
            name:"张三",
            age:18,
            food:['土豆','西红柿','茄子','芹菜'],
            girlFriend:[
                {name:"小红"},
                {name:"小粉"},
                {name:"小兰"}
            ]
        }
​
        let {name,age,food:[one,two,three,four],girlFriend:[first,second,thrid]} = obj;
        
        console.log(name); //张三
        console.log(thrid); //{name:"小兰"}
        console.log(one); // 土豆

注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式

2.4模板字符串

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

  1. 字符串中可以出现换行符
let a = `
        <ul>
            <li>赵本山</li>
            <li>小沈阳</li>
            <li>丫蛋</li></li>
            <li>刘能</li>
        </ul>
        `;
        console.log(a);
        // 输出结果
        /*<ul>
            <li>赵本山</li>
            <li>小沈阳</li>
            <li>丫蛋</li></li>
            <li>刘能</li>
        </ul>*/
  1. 可以使用 ${xxx} 形式输出变量
        let stu = "张三";
        let str = `${stu}明天就可以不上课了`;
        console.log(str); //张三明天就可以不上课了

<  注意:当遇见字符串与变量拼接的情况下使用模板字符串

2.5简化对象的写法

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

        let name = "张三";
        let fun = function(){
            console.log('我明天要上课');
        }
​
        let obj = {
            name,
            fun,
            stu(){
                console.log('明天是周六');
            }
        }
​
        console.log(obj); //{name: '张三', fun: ƒ}
        console.log(obj); //{name: '张三', fun: ƒ, stu: ƒ}

注意:对象简写形式简化了代码,所以以后用简写就对了

2.6箭头函数

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

    let sum = (a,b,c)=>{
            console.log(a+b+c);
        }
        sum(1,2,3) //6

箭头函数的注意点:

  1. 如果形参只有一个,则小括号可以省略
      let fun = a=>{
            console.log(a+a);
        }
        fun(2); //4
  1. 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
         let fun = a => a * a;
         let result = fun(3);
         console.log(result); //9
  1. 箭头函数 this 指向声明时所在作用域下 this 的值(this指向是静态的)
      let  name = "张三";
        function fun(){
            console.log(this.name);
        };
        let stu = ()=>{
            console.log(this.name);
        };
​
        fun();//张三
        stu();//张三
       
        const obj = {
            name:"孙悟空",
            age:18
        }
​
        fun.call(obj); //孙悟空
        stu.call(obj); //张三
  1. 箭头函数不能作为构造函数实例化
        // 普通函数
        let Person = function(name,age) {
            this.name = name;
            this.age = age;
        }
        let me = new Person("孙悟空",18);
        console.log(me); //Person {name: '孙悟空', age: 18}
​
        // 箭头函数
        let Stu = (name,age)=>{
            this.name = name;
            this.age = age;
        }
​
        let you = new Stu();
        console.log(you); //报错 Stu不是构造函数
  1. 不能使用 arguments
        //普通函数
        function name() {
            console.log(arguments);
        }
        name(1,2,3); //Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
        // 箭头函数
        let name1 = ()=>{
            console.log(arguments);
        }
        name1(1,2,3); // 报错 arguments is not defined

注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合

所以箭头函数适合与this无关的回调,定时器,数组方法的回调

2.6.1 点击div 2s后变色

点击以后变成粉红色

 //给div添加一个高度 宽度 背景色
<div id="ad"> </div>
    <script>
        //   获取元素
        let ad = document.getElementById('ad');
        // 绑定事件
        ad.addEventListener("click",function () {
            let _this = this;
            console.log(_this);
            // 定时器
            setTimeout( ()=>{
                this.style.background = 'pink'
            },2000)
            
        })
        </script>
2.6.2 数组返回偶数元素
        // 普通函数写法
        let arr = [1, 2, 4, 6, 9, 11];
        let a = arr.filter(function (item) {
            //  console.log(item);
            if (item % 2 == 0) {
                return true;
            } else {
                return false;
            }
        })
        console.log(a) //[2, 4, 6]
​
        // 箭头函数写法
      let b = arr.filter(item=> item % 2 == 0)
      console.log(b); //[2, 4, 6]

补充:函数参数的默认值设置

1.形参的初始值

形参的初始值,具有默认值的参数,一般位置要靠后(潜规则), 形参有默认值,如果传递的有实参就按照实参传递进去的,如果没有就按照形参的默认值

 function fun(a,b,c= 10){
            console.log(a+b+c);
        }
        fun(1,2) //13
        fun(1,2,3) //6
2.与解构赋值结合
 function stu ({name ='李四',age,gender,adress}){
            console.log(name); //张三 如果不传name 就是李四
            console.log(age);  //18 
            console.log(gender); //男
            console.log(adress); //河南
        };
        stu({
            // name:"张三",
            age:18,
            gender:"男",
            adress:"河南"
        });

2.7rest参数

ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments

     // rest参数
        function fun(...args) {
            console.log(args);
        }
        fun(1, 2, 3) // [1, 2, 3]
​
        //  rest 参数必须是最后一个形参
        function fun1(a, b, ...args) {
            console.log(a, b, args);
        }
        fun1(100, 1, 2, 3, 4, 5, 19);// 100 1 [2, 3, 4, 5, 19]

注意:rest 参数非常适合不定个数参数函数的场景

2.8spread 扩展运算符

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

 let arr = ['张三','李四','王五','刘六'];
        function fun(){
            // console.log(arguments); //['张三', '李四', '王五', '刘六']是一个数组
            console.log(arguments);  //变成了4个,分开的
        }
        fun(...arr);
2.8.1 合并数组
       let a = [1,2];
        let b = [3,4];
        // ES5语法
        // let arr = a.concat(b); [1, 2, 3, 4]
        // 扩展运算符
        let arr = [...a,...b];  //[1, 2, 3, 4]
        console.log(arr);
2.8.2 使用扩展运算符进行克隆
        let san = ['E','G','M'];
        let si = [...san];
        console.log(si); // ['E', 'G', 'M']

2.9 Symbol

2.9.1 Symbol的基本使用

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

Symbol 特点

  1. Symbol 的值是唯一的,用来解决命名冲突的问题
        // 创建Symbol值
        let a = Symbol();
        console.log(a); //Symbol
​
        // 添加表示Symbol
        let b = Symbol('张三');
        let c = Symbol('张三');
        console.log(b); //Symbol(张三)
        console.log(c); //Symbol(张三)
        console.log(b == c); //false
​
        // 使用Symbol for创建 获得唯一symbol值
        let d = Symbol.for('李四');
        let e = Symbol.for('李四');
        console.log(d);  //Symbol(李四)
        console.log(e);  //Symbol(李四)
        // console.log(d == e); //true
  1. Symbol 值不能与其他数据进行运算
  let a = Symbol();
        // let b = a+a; //报错
         b = a>100      //报错
        console.log(b);
  1. Symbol 定义的对象属性不能使用 for…in 循环遍历, 但是可以使用Reflect.ownKeys 来获取对象的所有键名
2.9.2给对象添加放方法

可以给对象添加属性属性和方法,如果不知道原来的对象有没有这个方法和属性,可以使用Symbol来进行更加安全的添加属性和方法。

 // Symbol的使用 第一无二的值,给对象添加属性和方法
     const obj ={
         name:"孙悟空",
         up:function(){
             console.log("我是up");
         },
         down:function(){
             console.log("我的dowm");
         }
     }
     
​
    // 声明一个对象
    const a = {
        up:Symbol(),
        down:Symbol()
    }
​
    // 这样添加一个值更加安全
    obj[a.up] = function (){
        console.log("我是symbol里的up");
    }
    obj[a.down] = function (){
        console.log("我是symbol里的down");
    }
​
    console.log(obj); //name: '孙悟空', up: ƒ, down: ƒ, Symbol(): ƒ, Symbol(): ƒ}

2.10 迭代器

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

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

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

a) Array

b) Arguments

c) Set

d) Map

e) String

f) TypedArray

g) NodeList

 let arr = ["唐僧","孙悟空","猪八戒","沙僧"];
​
        for(let i of arr){
            console.log(i); //唐僧,孙悟空 猪八戒 沙僧
        }
​
        // 创建一个指针对象,指向当前数据结构的起始位置
        let iterator = arr[Symbol.iterator]();
​
        //第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
        console.log(iterator.next()); //{value: '唐僧', done: false}
        //接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
        console.log(iterator.next()); //{value: '孙悟空', done: false}
        console.log(iterator.next()); //{value: '猪八戒', done: false}
        console.log(iterator.next()); //{value: '沙僧', done: false}
         //   每调用 next 方法返回一个包含 value 和done 属性
        //  done : 表示是结束
        console.log(iterator.next()); //{value: undefined, done: true}
  1. 工作原理

a) 创建一个指针对象,指向当前数据结构的起始位置

b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员

c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员对象

d) 每调用 next 方法返回一个包含 value 和done 属性的对象注 : 需要自定义遍历数据的时候,要想到迭代器。

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

2.2.1迭代器的使用

可以根据自己来定义,原理可以看迭代器的工作原理

const obj = {
            name:"xiyou",
            stus:[
                '唐僧',
                '孙悟空',
                '猪八戒',
                '沙僧'
            ],
            [Symbol.iterator](){
                // 索引变量 
                let index = 0;
                return {
                    next:()=>{
                        if(index < this.stus.length){
                            const result = {value:this.stus[index],done:false};
                            // 下标自增
                            index++;
                            // 返回结果
                            return result;
                        }else{
                            return {value:undefined,done:true};
                        }
                    }
                }
            }
        }
​
      
      for(let i of obj){
          console.log(i); //唐僧 孙悟空 猪八戒 沙僧
      }

2.11生成器

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

代码说明:

function* gen() {
            yield '一只没有耳朵'; 
            yield '一只没有尾巴'; 
            return '真奇怪';
        }
        let iterator = gen(); 
        console.log(iterator.next()); // {value: '一只没有耳朵', done: false}
        console.log(iterator.next());//{value: '一只没有尾巴', done: false}
        console.log(iterator.next());//{value: '真奇怪', done: true}
        console.log(iterator.next());//{value: undefined, done: true}
    • 的位置没有限制(可以在左边,也可以在右边,也可以在中间)
  1. 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到yield 语句后的值

  2. yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码

  3. next 方法可以传递实参,作为 yield 语句的返回值

2.11.1生成器函数的参数
function * gen(arg) {
            console.log(arg);
           let one =  yield 111; 
           console.log(one);
           let two =  yield 222; 
           console.log(two);
           let three= yield 333;
           console.log(three);
        }
        // 执行获取迭代器对象
        let iterator = gen('aaa'); 
        // 执行第一个next()执行第一句代码
        console.log(iterator.next());  //aaa
        // next可以传入实参 传入的实参 会成为 yield的返回值
        console.log(iterator.next('bbb'));  //bbb      
        console.log(iterator.next('ccc'));   //ccc
        console.log(iterator.next('ddd')); //ddd
2.11.2 案例1

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();
            },1000)
        };
​
        function two(){
            setTimeout(()=>{
                console.log(222);
                // 执行下一个
                iterator.next();
            },2000)
        };
​
        function three(){
            setTimeout(()=>{
                console.log(333);
                // 执行下一个
                iterator.next();
            },3000)
        };
​
        // 声明一个生成器函数
        function * gen(){
            yield one();
            yield two();
            yield three();
        }
        // 执行迭代器对象
        let iterator = gen();
        // 开始执行
        iterator.next();
2.11.3案例2

模拟获取 用户数据 订单数据 商品数据

 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 users = yield getUsers();
         console.log(users);
        let orders = yield getOrders();
        console.log(orders);
        let goods = yield getGoods();
        console.log(goods);
        }
​
        let iterator = gen();
        iterator.next(); 

2.12 Promise

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

用来封装异步操作并可以获取其成功或失败的结果。

        // 实例化 Promise对象
        let a = new Promise(function (resolve, reject) {
            setTimeout(function () {
                // let a = "你好";
                // resolve(a)
                // reject(a);
                let err = "没有获取数据";
                reject(err);
            }, 1000)
        });
        // 调用Promise 对象的then方法
        a.then(function (value) {
            console.log(value);//你好
        }, function (reason) {
            console.log(reason); // 没有获取数据
        });
  1. Promise 构造函数: Promise (excutor) {}

  2. Promise.prototype.then 方法

调用then方法 then方法返回结果是Promise对象,对象状态由回调函数执行结果决定

  • 如果回调函数中返回的结果是非 Promise类型的属性,状态为成功,返回值就是对象的成功的值

        let a = new Promise((resolve, reject) => {
                setTimeout( ()=> {
                    resolve('用户成功的数据')
                }, 1000)
            });
            // 调用Promise 对象的then方法
           let yhl =  a.then( value => {console.log(value); return 123;}, 
            reason =>
                console.log(reason)
            );
            
            console.log(yhl);  //Promise是成功的   值是123
    
  • 如果回调函数的返回结果是Promise类型的属性,根据内部promsie决定then promise返回的状态

    let a = new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve('用户成功的数据')
                }, 1000)
            });
            // 调用Promise 对象的then方法
            let yhl = a.then(value => { console.log(value); return new Promise((resolve,reject) =>{
                 reject('ok')
            }); },
                reason =>
                    console.log(reason)
            );
    ​
            console.log(yhl);  //Promise失败的  值是OK
    
  • 抛出错误 失败的 错误的值就是抛出去的值

    let a = new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve('用户成功的数据')
                }, 1000)
            });
            // 调用Promise 对象的then方法
            let yhl = a.then(value => { console.log(value); throw new Error('失败')},
                reason =>
                    console.log(reason)
            );
    ​
            console.log(yhl);  //失败  值就是抛出去的值
    
  1. Promise.prototype.catch 方法
2.12.1Promise封装node读取文件
// 第一步 引入fs模块
const fs = require('fs');
​
// 调用方法
fs.readFile('./练习.txt', (err, data) => {
    if (err) throw err;
    // console.log(data.toString());
});
​
​
// 使用Promsie 
const a = new Promise(function (resolve, reject) {
    fs.readFile('./练习.txt', function (err, data) {
        if (err) reject(err);
        resolve(data);
    })
});
​
a.then(function (value) { console.log(value.toString()); },
    function (reason) { console.log('读取失败'); })

文件

//练习
春晓
春眠不觉晓,
处处闻啼鸟,
夜来风雨声,
花落知多少。
//练习2
相思
红豆生南国,
春来发几枝。
愿君多采撷,
此物最相思。
//练习3
江雪
千山鸟飞绝,
万径人踪灭。
孤舟蓑笠翁,
独钓寒江雪。
2.12.2Promise封装 AJAX

原生写法

 // 原生写法
        // 第一步  创建一个对象
        const xhr = new XMLHttpRequest();
        // 第二步 初始化
        xhr.open("GET","http://127.0.0.1:3000");
        // 发送
        xhr.send();
        // 绑定事件 处理响应结果
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4){
                // 判断状态码200-299
                if(xhr.status >= 200 && xhr.status < 300){
                    // 表示成功
                    console.log(xhr.response); //这是get请求
                }else{
                    console.log(xhr.status);
                }
            }
        }

服务器代码

//需要安装 express
const express = require('express');
const app = express();
​
app.get('/',(req,res)=>{
    // response.send(123)
    res.setHeader("Access-Control-Allow-Origin","*")
    res.send("这是get请求");
})
​
app.listen('3000',()=>{
    console.log("启动");
})

使用Promise进行封装

  const yhl = new Promise(function (resolve, reject) {
            const xhr = new XMLHttpRequest();
            // 第二步 初始化
            xhr.open("GET", "http://127.0.0.1:3000");
            // 发送
            xhr.send();
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    // 判断状态码200-299
                    if (xhr.status >= 200 && xhr.status < 300) {
                        // 表示成功
                        resolve(xhr.response)
                    } else {
                        reject(xhr.status);
                    }
                }
            }
        });
​
        yhl.then(function (value) { console.log(value); },
            function (reason) { console.log("promise错误"); })
2.12.3 then链式案例
//原生写法
// 引入fs
const fs = require('fs');
​
fs.readFile('./练习.txt', (err, data1) => {
    fs.readFile('./练习2.txt', (err, data2) => {
        fs.readFile('./练习3.txt', (err, data3) => {
            let result = data1 + '\r\n' + data2 + '\r\n' + data3;
            console.log(result);
        });
    });
});
​
//运行结果就是:三首诗,顺序被读取

promise写法

// 引入fs
const fs = require('fs');
​
const yhl = new Promise((resolve, reject) => {
    fs.readFile('./练习.txt', (err, data) => {
        resolve(data)
    })
});
​
yhl.then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile('./练习2.txt', (err, data) => {
            resolve([value, data])
        })
    })
}).then(
    value => {
        return new Promise((resolve, reject) => {
            fs.readFile('./练习3.txt', (err, data) => {
                value.push(data);
                resolve(value)
            })
        })
    }
).then(value => console.log(value.toString()))
​
//运行结果就是:三首诗,顺序被读取

文件

//练习
春晓
春眠不觉晓,
处处闻啼鸟,
夜来风雨声,
花落知多少。
//练习2
相思
红豆生南国,
春来发几枝。
愿君多采撷,
此物最相思。
//练习3
江雪
千山鸟飞绝,
万径人踪灭。
孤舟蓑笠翁,
独钓寒江雪。
2.12.4 封装sendAJAX
 function sendAJAX(url) {
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                // 第二步 初始化
                xhr.open("GET", url);
                // 发送
                xhr.send();
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        // 判断状态码200 - 299
                        if (xhr.status >= 200 && xhr.status < 300) {
                            // 表示成功
                            resolve(xhr.response)
                        } else {
                            reject(xhr.status);
                        }
                    }
                }
            })
        }
        
        // 使用then方法
        sendAJAX("http://127.0.0.1:3000").then(value => {console.log(value);}) //这是get请求
​
        // 使用async await
        async function fun(){
            let result = await sendAJAX("http://127.0.0.1:3000");
            console.log(result); //这是get请求
        }
        fun();

服务器代码

//需要安装 express
const express = require('express');
const app = express();
​
app.get('/',(req,res)=>{
    // response.send(123)
    res.setHeader("Access-Control-Allow-Origin","*")
    res.send("这是get请求");
})
​
app.listen('3000',()=>{
    console.log("启动");
})

2.13 Set

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

  1. size 返回集合的元素个数

  2. add 增加一个新元素,返回当前集合

  3. delete 删除元素,返回 boolean 值

  4. has 检测集合中是否包含某个元素,返回 boolean 值

  5. clear 清空集合,返回 undefined

    // 声明一个Set
    // let a = new Set();
    // console.log(a); //Set(0) {size: 0}
​
    // 初始参数,可迭代数据  会自动去重
​
    let a = new Set(['孙悟空','猪八戒','沙和尚','唐僧','孙悟空']); 
    console.log(a); //Set(4) {'孙悟空', '猪八戒', '沙和尚', '唐僧'} 返回的是一个类数组对象
     
    // 元素个数
    console.log(a.size); //4
​
    // 添加一个元素
    let b = a.add('小白龙');
    console.log(b); //{'孙悟空', '猪八戒', '沙和尚', '唐僧', '小白龙'}
    
    // 删除一个元素  返回boolean值
    let c = a.delete('沙和尚');
    console.log(c); //true
    
    // 检测是否一个值 返回是一个boolean
    let s = a.has('孙悟空')
    console.log(s); // true
    let d = a.has('白骨精');
    console.log(d); //false
    
    // 清除集合
    let e = a.clear();
    console.log(e);  //undefined// 使用for of 遍历
    for(let v of a){
        console.log(v); // 孙悟空 猪八戒 沙和尚 唐僧 小白龙
    }
2.13.1 集合实践

数组去重

     // 数组去重
    let arr = [1, 2, 3, 4, 3, 1];
    let a = [...new Set(arr)];  //返回一个类数组对象
    console.log(a); // [1, 2, 3, 4]

交集

    // 交集
    //基础写法 
    let arr = [1, 2, 3, 4, 3, 1];
    let arr2 = [2, 3, 4, 5, 2];
    let result = [...new Set(arr)].filter(item => {
        let b = new Set(arr2);
        if (b.has(item)) {
            return true;
        } else {
            return false;
        }
    })
    console.log(result); //[2, 3, 4]
​
    // 简化写法 
    let yhl = [...new Set(arr)].filter( item => new Set(arr2).has(item));
    console.log(yhl); // [2, 3, 4]

并集

    // 并集
    let arr = [1, 2, 3, 4, 3, 1];
    let arr2 = [2, 3, 4, 5, 2];
    let result = [...new Set([...arr,...arr2])];
    console.log(result); //[1, 2, 3, 4, 5]

错集

    //  差集
    let arr = [1, 2, 3, 4, 3, 1];
    let arr2 = [2, 3, 4, 5, 2];
    let result = [...new Set(arr)].filter( item => !(new Set(arr2).has(item)));
    console.log(result); //[1]

2.14Map

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

  1. size 返回 Map 的元素个数
        // 定义一个map
        let s = new Map();
        
        // 新增一个元素
        s.set('name',"孙悟空");
        s.set('change',function(){
            console.log('我们是西游记师徒四人');
        });
        
        console.log(s.size);  // 2
  1. set 增加一个新元素,返回当前 Map
      // 定义一个map
        let s = new Map();
        
        // 新增一个元素
        s.set('name',"孙悟空");
        s.set('change',function(){
            console.log('我们是西游记师徒四人');
        });
        let key = {
            adress:"四人地方"
        }
        s.set(key,['花果山','高老庄','流沙河']);
        console.log(s); // {'name' => '孙悟空', 'change' => ƒ, {…} => Array(3)}  key就是第一个 value就是第二个
  1. get 返回键名对象的键值
        console.log(s.get('name')); //孙悟空
        console.log(s.get('change')); //ƒ (){console.log('我们是西游记师徒四人');}
  1. has 检测 Map 中是否包含某个元素,返回 boolean 值
        console.log(s.has('name')); //true
        console.log(s.has('nnn'));  //false

clear 清空集合,返回 undefined

         //清空
        s.clear();
        console.log(s); //Map(0) {size: 0}
        
​
         //for of 遍历
          for(let v of s){
            console.log(v); // ['name', '孙悟空']   ['change', ƒ]
        }

2.15 class类

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

知识点:

  1. class 声明类
 // ES5
         let Phone = function(pin,price){
                this.pin = pin,
                this.price = price
         };
​
         Phone.prototype.call = function(){
             console.log("我的手机很nice");
         };
​
        // 实例化对象
        let Huawei = new Phone('红米',2499);
        Huawei.call();      //我的手机很nice
        console.log(Huawei); //Phone {pin: '红米', price: 2499}
​
​
​
        // class类
        class Shou {
            // 构造方法 名字不可以修改
            constructor(pin,price){
                this.pin = pin,
                this.price = price
            }
            // 方法必须是这种写法,不能使用ES5对象完整形式
            call(){
                console.log('我的手机也不错');
            }
        }
​
        let result = new Shou('OPPO',2899);
        result.call(); //我的手机也不错
        console.log(result); //Shou {pin: 'OPPO', price: 2899}
  1. constructor 定义构造函数初始化

  2. extends 继承父类(3.4一个案例)

  3. super 调用父级构造方法

 class Phone {
            // 构造方法
            constructor(pin,price){
                this.pin = pin,
                this.price = price
            }
            // 父类的成员属性
            call(){
                console.log('我是手机');
            }
        }
​
        class SmartPhoen extends Phone {
            // 构造方法
            constructor(pin,price,color,size) {
                super(pin,price);
                this.color = color;
                this.size = size;
            }
            photo(){
                console.log("拍照");
            }
​
            game(){
                console.log("打游戏");
            }
        }
​
        let yhl = new SmartPhoen("红米",2999,"渐变色","1.23");
        console.log(yhl); //SmartPhoen {pin: '红米', price: 2999, color: '渐变色', size: '1.23'}
        yhl.call(); //我是手机
        yhl.photo();//拍照
        yhl.game(); //打游戏
  1. static 定义静态方法和属性
class Phone{
            static name = "孙悟空";
            static change = function (){
                console.log('我的手机可以');
            };
        }
​
        let yhl = new Phone();
        console.log(yhl.name); //undefided
        console.log(Phone.name); // 孙悟空
        console.log(Phone.change); //ƒ (){console.log('我的手机可以');}
  1. 父类方法可以重写

调用的是紫类call方法,不是父类。在js语法中子类是不可以直接调用父类的

class Phone {
            // 构造方法
            constructor(pin,price){
                this.pin = pin,
                this.price = price
            }
            // 父类的成员属性
            call(){
                console.log('我是手机');
            }
        }
​
        class SmartPhoen extends Phone {
            // 构造方法
            constructor(pin,price,color,size) {
                super(pin,price);
                this.color = color;
                this.size = size;
            }
            photo(){
                console.log("拍照");
            }
​
            game(){
                console.log("打游戏");
            }
​
            call(){
                console.log("我可以视频通话");
            }
        }
​
        let yhl = new SmartPhoen("红米",2999,"渐变色","1.23");
        console.log(yhl); //SmartPhoen {pin: '红米', price: 2999, color: '渐变色', size: '1.23'}
        yhl.call(); //我可以视频通话
        yhl.photo();//拍照
        yhl.game(); //打游戏

2.16数值扩展

2.16.1 二进制和八进制

ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和 0o 表示 十六进制用0x表示。

     let a = 0b0101; //二进制
      let b = 0o0014 // 八进制
      let c = 100;   //十进制
      let d = 0x0014; // 十六进制
      console.log(a); //5
      console.log(b); //12
      console.log(c); //100
      console.log(d); //20
2.16.2 Number.isFinite()与 Number.isNaN()

Number.isFinite() 用来检查一个数值是否为有限的

 console.log(Number.isFinite(100)); //true
 console.log(Number.isFinite('hello')); //false

Number.isNaN() 用来检查一个值是否为 NaN ,如果是一个数字就返回false 如果不是一个数字就返回true

console.log(isNaN(123)); //false
console.log(isNaN('hello')); //true
2.16.3Number.parseInt() 与 Number.parseFloat()

ES6 将全局方法 parseInt 和 parseFloat,字符串转整数。

   let a = '5211314Iloveyou';
   let b = '3.1415926yuanzhoulv';
    console.log(Number.parseInt(a));  //5211314
    console.log(Number.parseFloat(b)); // 3.1415926
2.16.4 Math.trunc

用于去除一个数的小数部分,返回整数部分。

 console.log(Math.trunc(2.3)); //2
2.16.5 Number.isInteger

Number.isInteger() 用来判断一个数值是否为整数

console.log(Number.isInteger(1)); //true
console.log(Number.isInteger(1.3)); //false

2.17 对象的方法扩展

ES6 新增了一些 Object 对象的方法

  1. Object.is 比较两个值是否严格相等,与『===』行为基本一致(+0 与 NaN)
console.log(Object.is(NaN,NaN)); //true
console.log(NaN === NaN); //false
  1. Object.assign 对象的合并,将源对象的所有可枚举属性,复制到目标对象

传递两个参数 第一个参数是目标对象 第二个参数是源对象 如果有同样的属性名 会进行覆盖

onst obj = {
            name:"孙悟空",
            chenghao:"齐天大圣",
            adress:"花果山"
        }
​
        const obj1 = {
            name: "猪八戒",
            adress:"高老庄",
            gender:"男"
        }
        let result = Object.assign(obj,obj1);
        console.log(result); //{name: '猪八戒', chenghao: '齐天大圣', adress: '高老庄', gender: '男'}
  1. setPrototypeOf、 setPrototypeOf 可以直接设置对象的原型
 const team = {
            name:"师徒四人"
        };
​
        const adress = {
            diFang : ["花果山","高老庄","流沙河"]
        };
​
        Object.setPrototypeOf(team,adress);
        console.log(team); //可以在原型上看见

2.18模块化

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

2.18.1 模块化的好处

模块化的优势有以下几点:

  1. 防止命名冲突

  2. 代码复用

  3. 高维护性

2.18.2 模块化规范产品

ES6 之前的模块化规范有:

  1. CommonJS => NodeJS、Browserify 2) AMD => requireJS 3) CMD => seaJS
2.18.3ES6模块化语法

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

  • export 命令用于规定模块的对外接口
  • import 命令用于输入其他模块提供的功能
2.18.1 export 三种暴露方式
  • 分别暴露

    //m1.js
    // 分别暴露
     export let name = '孙悟空';
    export function fun(){
       console.log('我可以三打白骨精');
    };
     //引入 在script标签里 需要有type="module" 
     import * as m1 from './m1.js';
     console.log(m1); //Module {Symbol(Symbol.toStringTag): 'Module'} 里面会有孙悟空  fun函数
  • 统一暴露

    //m2.js
    //统一暴露
    let name = '猪八戒';
    function fun(){
        console.log("我能回高老庄");
    }
    export {name,fun};//引入 在script标签里 需要有type="module" 
    import * as m1 from './m2.js';
    console.log(m2); //Module {Symbol(Symbol.toStringTag): 'Module'} 里面会有猪八戒  fun函数
    
  • 默认暴露

    //m3.js
    //默认暴露
    export default {
          name : '沙和尚',
          function:function(){
              console.log('我在流沙河');
          }
    }
    ​
    //引入 在script标签里 需要有type="module" 
    import * as m1 from './m3.js';
    console.log(m3); //Module {Symbol(Symbol.toStringTag): 'Module'}  里面有沙和尚 fun函数, 不过里面会多一层 default
    
    2.18.2 ES6引入模块数据
    • 通用的导入的方式

      import * as m1 from './m1.js';
      console.log(m1); //下图import * as m1 from './m2.js';
      console.log(m2); //下图中的孙悟空变成猪八戒
      import * as m1 from './m3.js';
      console.log(m3); //下图
      

image-20220414105858237.png

image-20220414105809766.png

  • 解构赋值形式

            // 解构赋值类型
            import{name,fun} from './m1.js';
            console.log(name); //孙悟空
            console.log(fun); //ƒ fun(){console.log('我可以三打白骨精');}
    
            // 如果出现重名 可以通过起别名的方法解决
            import{name as name1 ,fun as fun1} from './m2.js'; 
            console.log(name1); //猪八戒 
            console.log(fun1); //ƒ fun(){console.log("我能回高老庄");}
          
            import {default as m3} from './m3.js'
            console.log(m3); //{name: '沙和尚', function: ƒ}
    
  • 简便形式(只针对 默认暴露)

     // 简单类型 只对默认暴露有用
            import m3 from './m3.js'
            console.log(m3); //{name: '沙和尚', function: ƒ}
    

第三章 ECMASript 7 新 特 性

3.1 includes

方法用来检测数组中是否包含某个元素,返回布尔类型值 之前可以用indexOf(),没有返回-1

let arr = ['孙悟空','猪八戒','沙和尚','唐僧'];
console.log(arr.indexOf('白骨精')); //-1console.log(arr.includes('孙悟空')); //true
console.log(arr.includes('小白龙')); //false

3.2 指数操作符

在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同

let a = 2 ** 5;
let b = Math.pow(2,5)
console.log(a); //32
console.log(b); //32

第四章 ECMAScript 8 新特性

4.1. async 和 await

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

4.1.1. async 函数
  1. async 函数的返回值为 promise 对象,
  2. promise 对象的结果由 async 函数执行的返回值决定
 async function fun(){
            // 返回一个字符串
            // 返回的结果不是一个Promise类型的对象 返回的结果就是成功的Promise对象
            // return 'ok'
​
            // 抛出错误就会返回一个失败的Promise
            // throw new Error('失败啦');
​
            // 返回的是一个promise对象 
            // 如果里面的是一个成功的promise async函数也会是一个成功的 否则就是失败的
            return new Promise((resolve,reject)=>{
                // resolve('获取到了数据');
                reject('没有获取到数据');
            })
        };
        let fn = fun();
        // console.log(fn); //是一个成功的Promise ok就是他的返回值
        // console.log(fn); //一个失败的Promise
        console.log(fn); //是一个成功的promise 返回值是获取到了数据
        console.log(fn); // 是一个失败的promise 
4.1.2. await表达式
  1. await 必须写在 async 函数中
  2. await 右侧的表达式一般为 promise 对象
  3. await 返回的是 promise 成功的值
  4. await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理
   // 创建一个Promise对象
           let a = new Promise((resolve, reject) => {
               resolve('成功啦')
               // reject('失败啦')
           })
   
           // await 必须在 async这个函数中 如果失败就用try catch
           async function fun() {
               try {
                   let result = await a;
                   console.log(result); //成功啦
               } catch (error) {
                       console.log(error); //失败啦
               }
           }
   
           fun();
4.1.3 async 和await使用读取文件
//  引入fs模块
const fs = require('fs')
​
// 使用promsie封装练习的古诗
function test(){
    return new Promise((resolve,reject)=>{
        fs.readFile('./练习.txt',(err,data)=>{
            if(err) reject(err);
            resolve(data)
        })
    })
}
​
// 使用promsie封装练习2的古诗
function test2(){
    return new Promise((resolve,reject)=>{
        fs.readFile('./练习2.txt',(err,data)=>{
            if(err) reject(err);
            resolve(data)
        })
    })
}
​
// 使用promsie封装练习3的古诗
function test3(){
    return new Promise((resolve,reject)=>{
        fs.readFile('./练习.txt',(err,data)=>{
            if(err) reject(err);
            resolve(data)
        })
    })
}
​
// 声明一个async函数
async function fun(){
    let result = await test();
    let result1 = await test2();
    let result2 = await test3();
    // 获取练习的古诗内容
    console.log(result.toString());
    // 获取练习2的古诗内容
    console.log(result1.toString());
    // 获取练习3的古诗内容
    console.log(result2.toString());
};
fun();  //运行结果如下

image-20220414105553414.png

4.2. Object.values 和 Object.entries

  1. Object.values()方法返回一个给定对象的所有可枚举属性值的数组

  2. Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组

    const yhl = {
                name:"孙悟空",
                age:18,
                sex:"男",
                adress:'花果山'
            }
            
            console.log(Object.keys(yhl)); //['name', 'age', 'sex', 'adress']
            console.log(Object.values(yhl)); // ['孙悟空', 18, '男', '花果山']
            console.log(Object.entries(yhl));//运行结果如下
    

image-20220414105412304.png

4.3. Object.getOwnPropertyDescriptors

该方法返回指定对象所有自身属性的描述对象

console.log(Object.getOwnPropertyDescriptors(yhl));
//运行代码如下 

image-20220414110344877.png

第五章 ECMAScript 9 的特性

5.1Rest和spread

Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组, 在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符

rest参数

function fun({name,age,...user}){
        console.log(name);  // 孙悟空
        console.log(age);   //18
        // console.log(adress); //花果山
        // console.log(chuoHao); //齐天大圣
        console.log(user); // {adress: '花果山', chuoHao: '齐天大圣'} 会把剩下的属性,放到user对象中
    };
​
    fun({
        name:"孙悟空",
        age:18,
        adress:"花果山",
        chuoHao:"齐天大圣"
    })

spread 扩展运算符

const obj = {
        name:"孙悟空"
    }
​
    const obj1 = {
        age:18
    }
​
    const obj2 = {
        adress:"花果山"
    }
​
    const obj4 = {...obj,...obj1,...obj2}
    console.log(obj4); //{name: '孙悟空', age: 18, adress: '花果山'}

第 6 章 ECMASript 10 新 特 性

6.1. Object.fromEntries

参数是一个二维数组,或者是一个map 可以将一个二维数组转化成一个对象

 let arr = [['name','孙悟空'],['age',18]];
 console.log(Object.fromEntries(arr)); //{name: '孙悟空', age: 18}

6.2.trimStart 和 trimEnd

// trim  es5语法 清除两侧空白
    let a = "  12  "  
    
    console.log(a+"没有清除空白"); //   
    console.log(a.trim() + "清除两侧空白"); //
    // es10引进了 trimStart()  清除左侧空白    trimEnd()清除右侧空白
    console.log(a.trimStart()+"清除左侧空白"); 
    console.log(a.trimEnd() + "清除右侧空白"); 

运行结果

image-20220414120809677.png

6.3.Array.prototype.flat与 flatMap

// flat  平   将多维数组转化为低位数组
    let arr = [1,2,3,4,[5,6]];
    console.log(arr.flat()); // [1, 2, 3, 4, 5, 6]
    let arr2 = [1,2,3,4,[5,6,[7,8]]]
    console.log(arr2.flat()); //[1, 2, 3, 4, 5, 6, Array(2)]
    // 可以传递参数表示深度
    console.log(arr2.flat(2));// [1, 2, 3, 4, 5, 6, 7, 8]
​
    // mapFlat
​
    let arr3 = [1,3,4];
    // let a = arr3.map(item  => item*10);
    // console.log(a); //[10, 30, 40]
​
    let a = arr3.flatMap(item => [item*10])
    console.log(a); //[10, 30, 40]

6.4.Symbol.prototype.description

获取Symbol字符串描述

let s = Symbol('孙悟空');
console.log(s.description); //孙悟空

7ECMASript 11 新 特 性

7.1. 类的私有属性

   class Person {
            // 公有属性
            name;
            // 私有属性 需要加一个#号
            #age;
            #wight;
            // 构造方法
            constructor(name, age, wight) {
                this.name = name;
                this.#age = age;
                this.#wight = wight;
            }
​
            getName() {
                console.log(girl.name); //白骨精
                console.log(girl.#age); // 18
                console.log(girl.#wight); //45kg
            }
        }
​
        const girl = new Person("白骨精", 18, "45kg");
        // console.log(girl.name);
        // console.log(girl.#age);  //会获取不到数据,外部不可以获取到
        // console.log(girl.#wight);
        // console.log(girl);//Person {name: '白骨精', #age: 18, #wight: '45kg'}
        console.log(girl.getName());

7.2Promise.allSettled

接收一个promise数组,返回也是一个promise对象 返回的结果永远是成功的

  const p1 = new Promise((resolve,reject) =>{
            setTimeout((
                resolve('获取成功 -1')
            ),1000)
        });
​
        const p2 = new Promise((resolve,reject) =>{
            setTimeout((
                // resolve('获取成功 -2')
                reject('出错啦')
            ),1000)
        });
​
        // 返回的结果永远的成功的,就算有一个不会成功还是会返回成功的
        // const result = Promise.allSettled([p1,p2]);
        // console.log(result); //如下图
        // 一旦有一个不成功 就会返回失败
        const yhl = Promise.all([p1,p2])
        console.log(yhl); //有一个有问题,就报错

image-20220414150533561.png

7.3. 可选链操作符(?.)

使用场景:当我们对对象类型的参数的时候,层级比较多,有了它以后可以不进行层级判断

function fun(config) {   
             // 原始写法
            // const db = config && config.name && config.name.name1;
            // console.log(db);  //123 如果不传就会报错
            const db = config ?. name ?. name1;
            console.log(db); //123 如果不传值 不会报错 会显示undefined
        };
​
        fun({
            name: {
                name1: "123",
                host: "12334"
            },
            yhl: {
                name1: "345",
                host: "232323"
            }
        });

7.4. 动态 import 导入

点击一下按钮 控制台会打印出来hello

html代码

<button id="btn">点击一下</button>
<script src="./23测试.js" type="modele">

app.js代码

let btn = document.getElementById('btn');
​
btn.onclick = function(){
    // 直接写路径
    import('./24hello.js').then(module =>{
         module.fun(); //hello
    })
}

hello.js

//导出fun函数   
export function fun(){
    console.log('hello');
}

7.5. globalThis 对象

如果想对全局对象做一个操作,可以忽略环境直接使用 ,始终指向全局对象的。

7.6 BigInt

大整形

        // 大整形 在整数后面直接加一个n就可以了
        let a = 123n;
        console.log(a,typeof a); //123n 'bigint'
​
        // 函数
        let s = 123;
        console.log(BigInt(s)); //123n
        console.log(BigInt(1.2)); //报错,不可以是小数

看着视频整理的,只是一个大概,好多细节知识还需要整理,如果有错误的地方或者有歧义的,欢迎大家指正。