ES6语法规范

一、简介

  1. js由三部分组成:ES+DOM(文档对象模型)+BOM(浏览器对象模型)

  2. ES作为核心,是一套标准,规范了语言的组成部分:语法、类型、语句、关键字、保留字。定义了数据结构和语法,定义了函数和对象的实现,包括原型链和作用域链的机制和实现。

JavaScript 的核心 ECMAScript 描述了该语言的语法和基本对象;

DOM 描述了处理网页内容的方法和接口;

BOM 描述了与浏览器进行交互的方法和接口;

二、let使用说明

let是ES6新引入的声明变量的方式,特点:

  1. 不能重复声明
let star = "123";
let star = "123";//Identifier "star" has already been declared
  1. 块级作用域,仅在代码块内生效。var是全局作用域
{
let person = "shandong"
}
console.log(person);
  1. 不存在变量提升
console.log(name);

let name = "张三";// Cannot access "name" before initialization

三、const使用说明

const相当于常量

  1. 一定要赋初始值
const A = 1
  1. 一般常量要大写
const A = 100;
console.log(A)
  1. 常量的值不能修改
A = 200//Assignment to constant variable.
  1. const也是块级作用域
{
const PLAYER = "李四";
}
console.log(PLAYER);//PLAYER is not defined
  1. 对数组和对象的对象修改,不算对常量的修改,不会报错,建议用const声明数组和对象
const FOOL = ["苹果","西瓜","水蜜桃","李子"];
FOOL.push("草莓");
console.log(FOOL);

四、变量的解析赋值

ES6允许按照一定的模式从数组或对象中提取值,对变量进行赋值,称之为变量的解析赋值

  1. 数组的结构
const F4 = ["刘能","赵四","小沈阳","宋小宝"];
let [liu,zhao,xiao,song] = F4;
console.log(liu);
console.log(zhao);
console.log(xiao);
console.log(song);
  1. 对象的结构
const Person = {
    name: "张三",
    age: 12,
    learn: function(){
        console.log("努力学习,找到好工作");
    }
}

let {name, age, learn} = Person;
console.log(name);
console.log(age);
console.log(learn);
learn();

五、模板字符串【“】

ES6引入新的声明字符串的方式【“】【””】【""】

  1. 声明
let str = `123`;
console.log(str, typeof str);
  1. 内容中可以直接出现换行符
let str =`<ul>
            <li>123</li>
            <li>345</li>
            <li>456</li>
            </ul>`
  1. 变量拼接
let hello = "hello";
let word = `${hello} word`;
console.log(word);

六、简化对象写法

ES6允许在大括号里,直接写入变量和函数,作为对象的属性和方法。

let name = "张三";
let learn = function(){
    console.log("张三在学习");
}

const person = {
    name,
    learn,
    dosometing(){
        console.log("做点什么比较好");
    }
}

console.log(person);
person.dosometing();
person.learn();

七、箭头函数的使用

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

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

不适合与this有关的回调。事件回调,对象的方法

原始函数的声明:

let fn = function (a,b){
    xxxxxx
    return xxx;
}

使用箭头函数声明:

let fn = (a,b) =>{
    return a + b;
}
// 函数调用
let result = fn(3,3)
console.log(result)

(一)使用规范:

  1. this是静态的。this始终指向函数声明时所在作用域下的this的值
function getName(){
    console.log(this.name);
}
let getName2 = ()=>{
    console.log(this.name);
}

window.name = "hello ES6";
const dog = {
    name: "你好"
}
//直接调用
getName();
getName2();

//call方法调用
getName.call(dog);
getName2.call(dog);
  1. 不能作为构造函数实例化对象
let person = (name,age) => {
    this.name = name;
    this.age = age;
}
let someone = new person("zhangsan",12);
console.log(someone);//Uncaught TypeError: person is not a constructor
  1. 不能使用argument变量
let fn = () =>{
    console.log(arguments);
}
fn(1,2,3);
  1. 箭头函数简写
//1)省略小括号,当形参只有一个的时候
let add = n => {
    return n+n;
}
console.log(add(10))

//2)省略花括号,当代码只有一条执行语句时,此时return必须省略,而且语句的执行结果就是返回值
let pow = n => n*n
console.log(pow(12))

八、函数参数默认值

ES6允许函数参数赋值初始值

  1. 形参初始值 具有默认值的参数,一般位置靠后(约定俗成)
function add (a,b,c=10){
    return a + b + c;
}
let result =add(1,2)
console.log(result)
  1. 与解构赋值结合,也可以进行初始化赋值
function connect ({host = "127.0.0.1",username,password,port}){
    console.log(host);
    console.log(username);
    console.log(password);
    console.log(port);
}
connect({
    // host:"localhost",
    username:"root",
    password:"root",
    port:3306
})

九、rest参数

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

  1. ES5获取实参的方式
function data (){
    console.log(arguments)//arguments是一个对象
}
data("dog","cat","pig")
  1. ES6的rest参数,是一个数组,可以使用数组相关的api如:filter some every map等
function data (...args){
    console.log(args)
}
data("dog","cat","pig")
  1. rest参数必须放到参数最后
function data (...args){
    console.log(args)
}
data("dog","cat","pig")

十、spread扩展运算符

【…】 扩展运算符能将【数组】转化为逗号分隔的【参数序列】

声明数组

const F4 = ["刘能","赵四","小沈阳","宋小宝"];

声明函数

function paozao(){
    console.log(arguments);
}
paozao(...F4)//相当于paozao("刘能","赵四","小沈阳","宋小宝")

扩展运算符的应用

  1. 数组的合并
const hello = ["h","e","l","l","o"];
const word = ["w","o","r","d"];
const helloword = hello.concat(word);
console.log(helloword)
  1. 数组的克隆
const copy = ["c","o","p","y"];
const copy2 = [...copy]
console.log(copy2)
  1. 将伪数组转化为真正的数组
const divs = document.querySelectorAll("div");
console.log(divs);
const divAll = [...divs];
console.log(divAll);

十一、symbol基本用法

介绍:Symbol是一种新的原始数据类型,表示独一无二的值,时javascript语言的第七种数据类型,是一种类似于字符串的数据类型

特点:

​ 1) Symbol的值是唯一的,用来解决命名冲突的问题

​ 2) Symbol值不能与其他的数据进行运算

​ 3) Symbol定义的对象属性不能使用for…in遍历循环,但是可以使用Reflect.ownKeys来获取对象的所有键名

创建Symbol

let s1 = Symbol();
console.log(s1,typeof s1);

let l1 = "hello";
let l2 = "hello";
console.log(l1 === l2);//true

let s2 = Symbol("hello");
let s3 = Symbol("hello");
console.log(s2 === s3);//false
Symbol.for创建
let s4 = Symbol.for("nihao");
let s5 = Symbol.for("nihao");
console.log(s4,typeof s4);

不能与其他数据进行运算

let result = s1 + 100;//Cannot convert a Symbol value to a number
let result = s1 > 100;//Cannot convert a Symbol value to a number
let result = s1 + "123";//Cannot convert a Symbol value to a string
let result = s1 + s1;//Cannot convert a Symbol value to a number

js常见数据类型总结:USONB: you are so niubility

​ u : undifined

​ s : string

​ o : object

​ b : boolean

声明对象

let methods = {
    up:Symbol(),
    down: Symbol()
};

game[methods.up] = function(){
    console.log("我可以上升")
}

game[methods.down] = function(){
    console.log("我可以下降")
}
console.log(game)

let lol = {
    name:"英雄联盟",
    [Symbol("yasuo")]:function(){
        console.log("快乐风男");
    },
    [Symbol("jiansheng")]:function(){
        console.log("无极剑圣")
    }
}
console.log(lol)

Symbol内置属性,提供了11种内置属性

十二、迭代器

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

1)ES6提供了一种新的遍历命令for…of循环,interator接口主要为for…of服务

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

​ a) Array

​ b) Arguments

​ c) Set

​ d) Map

​ e) String

​ f) TypedArray

​ g)NodeList

3)工作原理

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

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

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

​ d)每调用next方法返回一个包含 value和done属性的对象

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

const person = ["张三","李四","王五"];
for(let v of person){
    console.log(v);//"张三","李四","王五"
}
for(let v in person){
    console.log(v);//0,1,2
}
for...of保存的键值,for...in保存的键名

let iterator = person[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

迭代器自定义遍历对象

const banji = {
    name:"终极一班",
    stus:[
        "xiaoming",
        "xiaohong",
        "xiaotian",
        "xioahu"
    ],
    [Symbol.iterator](){
        let index = 0;
        let _this = this;
        return{
            next:function(){
                if(index < _this.stus.length){
                    const result = {value: _this.stus[index], done: false};
                    index++;
                    return result;
                }else{
                    return {value: undefined, done: true};
                }
            }
        };
    }
}
//遍历对象,要求用for...of遍历,且返回的为对象中数组的成员
for(let v of banji){
    console.log(v)
}

十三、生成器

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

声明方式,在function后面加*,调用时调用next()方法执行

生成器实现了iterator属性带有next()方法

yield语句函数代码的分隔符

function * gen(){
    console.log("hello generator")
    console.log(111);
    yield "一只没有耳朵";
    console.log(222);
    yield "一直没有尾巴";
    console.log(333);
    yield "真奇怪";
    console.log(444);
}

let iterator = gen();
// console.log(iterator)
iterator.next();
iterator.next();
iterator.next();
iterator.next();

//遍历
for(let v of gen()){
    console.log(v);
}

//生成器函数参数
function * gen(args){
    console.log(args)
    let one = yield 111;
    console.log(one);
    yield 222;
    yield 333;
}

let iterator = gen("AAA");
console.log(iterator.next());
//next()方法可以传入实参,参数作为上一个yield语句返回结果
console.log(iterator.next("BBB"));
console.log(iterator.next());
console.log(iterator.next());

异步编程(js是单线程执行的,操作需要异步执行) 文件读取 网络操作(ajax,request) 数据库操作

生成器函数实例-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()
    },1000)
}

function three (){
    setTimeout(() =>{
        console.log(333);
        iterator.next()
    },1000)
}

function * gen (){
    yield one();
    yield two();
    yield three();
}

let iterator = gen();
iterator.next();

生成器函数实例-2

模拟获取(依次获取) 用户数据 订单数据 商品数据

function getUsers (){
    setTimeout(() =>{
        let data = "获取用户数据"
        // 调用next()方法,并将数据传入
        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()

十四、promise

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

  1. Promise构造函数: Promise( executor){}

  2. Promise.prototype.then方法

  3. Promise.prototype.catch方法

使用方法

//实例化对象
const p = new Promise(function(resolve, reject){
    setTimeout(function(){
        let data = "数据库中的数据";
        resolve(data);

        let err = "读取数据失败";
        reject(err);
    },1000)
});

// 调用Promise对象的then方法
p.then(function(value){
    console.log(value);
},function(reason){
    console.error(reason);
})

Promise封装读取文件

const fs = require("fs");

const p = new Promise(function(resovle,reject){
    fs.readFile("./resources/test.txt",(err,data)=>{
        // 判断失败
        if (err) reject(err);
        // 成功
        resovle(data);
    });
});

p.then(function(value){
    console.log(value.toString());
},function(reason){
    console.error("操作失败");
})

Promise发送ajax请求

const p = new Promise((resolve,reject) => {
    // 1.创建对象
    const xhr = new XMLHttpRequest();
    // 2.初始化
    xhr.open("GET","https://api.apiopen.top");
    // 3.发送
    xhr.send();
    // 4.绑定事件,处理响应结果
    xhr.onreadystatechange = function (){
        // 处理逻辑
        if(xhr.status >= 200 && xhr.status < 300){
            // 响应成功
            resolve(xhr.response);
        }else{
            // 响应失败
            reject(xhr.status);
        }
    }
})
// 指定回调函数
p.then(function(value){
    console.log(value)
},function(reason){
    console.log(reason)
})

Promise的then()方法

const p = new Promise((resolve,reject) =>{
    setTimeout(() =>{
        resolve("用户数据");
    },1000);
});

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

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

const result = p.then(value =>{
    console.log(value);
     1.非Promise类型的属性
     return "good";
     2.Promise类型的属性
     return new Promise((resolve,reject) =>{
         resolve("ok");
         // reject("error");
     });
     3.抛出异常
     throw new Error("出错了!");
},reason =>{
    console.warn(reason);
});

console.log(result);

then()方法支持链式调用,链式调用可以解决回调地狱的问题

p.then(value=>{},reason=>{}).then(value={},reason=>{})

Promise-读取多个文件

const fs = require("fs");

使用回调地狱的方式实现
fs.readFile("./resources/test.txt", (err, data1) => {
    fs.readFile("./resources/test1.txt", (err, data2) => {
        fs.readFile("./resources/test3.txt", (err, data3) => {
            let result = data1 + "
" + data2 + "
" + data3;
            console.log(result);
        });
    });

});

// 采用Promise对象的方式实现多文件读取,采用链式调用的方式进行拼接操作
const p = new Promise((reslove,reject)=>{
    fs.readFile("./resources/test.txt",(err,data)=>{
        reslove(data);
    });
});

p.then(value=>{
    return new Promise((reslove,reject)=>{
        fs.readFile("./resources/test1.txt",(err,data)=>{
            reslove([value,data]);
        });
    });
}).then(value=>{
    return new Promise((reslove,reject)=>{
        fs.readFile("./resources/test3.txt",(err,data)=>{
            value.push(data);
            reslove(value);
        });
    });
}).then(value=>{
    console.log(value.join("
"));
})

Promise的catch()方法,用于指定Promise对象失败时的回调是语法糖,相当于没有指定value参数的then()方法

const p = new Promise((reslove,reject)=>{
    setTimeout(() => {
        reject("出错啦!");
    }, 1000);
});

// 通过then()方法的reason指定失败时的操作
p.then(value=>{},reason=>{
    console.error(reason);
});
//通过catch()方法获取Promise对象的异常
p.catch(reason=>{
    console.warn(reason);
})

十五、集合与相关的API

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

集合的属性和方法:

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

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

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

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

//声明一个set
let s = new Set();
let s2 = new Set([12,13,14,15,21,12]);
// console.log(s ,typeof s);
console.log(s2);
// 1) size   返回集合的元素个数
console.log(s2.size);
// 2) add    增加一个新元素,返回当前集合
s2.add(100);
console.log(s2);
// 3) delete 删除元素,返回 boolean值
s2.delete(15);
console.log(s2);
// 4) has    检测集合中是否包含某个元素,返回 boolean值
console.log(s2.has(100));
// 5) clear  清空集合
s2.clear();
console.log(s2);
// 6)for..of..遍历
for(v of s2){
    console.log(v);
}

//set集合的使用
let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let arr2 = [4,5,6,5,6];
//1.数组去重
let result = [...new Set(arr)];
console.log(result);
//2.交集
let result = [...new Set(arr)].filter(item =>{
    let s2 = new Set(arr2);
    if(s2.has(item)){
        return true;
    }else{
        return false;
    }
});
console.log(result);

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

十六、Map与相关的API

ES6提供了Map数据结构。它类似于对象也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

Map也实现了 Iterator接口,所以可以使用「扩展运算符…』和『for…0f…』进行遍历。

Map的属性和方法:

  1. size 返回Map的元素个数

  2. set 增加一个新元素,返回当前Map

  3. get 返回键名对象的键值

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

  5. clear 清空集合,返回 undefined

// 声明Map
let m = new Map();
// 添加元素
m.set("name","Tom");
m.set("function1",function(){
    console.log("hello");
});
let key = {
    school:"SDUT"
}
m.set(key,["2016","2017","2018"]);
console.log(m);
// map长度
console.log(m.size);
// 返回对象的键值
console.log(m.get("name"));
// has判断是否包含某个元素
console.log(m.has("function1"));
// 删除数据
m.delete("name");
console.log(m);
// clear清空map集合
m.clear();
console.log(m);

十七、Class类

ES6提供了更接近传统语言的写法,引入了dass(类)这个概念,作为对象的模板。通过cass关键字,可以定义类。

基本上,ES6的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,

新的 class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而己。

知识点:

  1. class 声明类

  2. constructor 定义构造函数初始化

  3. extends 继承父类

  4. super 调用父级构造方法

  5. static 定义静态方法和属性

6)父类方法可以重写

//使用class()声明类
class Computer {
    // 构造方法,名字不可修改,会在实例化对象的时候自动调用,可以没有
    constructor(brand, price) {
        this.brand = brand;
        this.price = price;
    }
    // 定义方法,不能使用ES5的方式声明
    start() {
        console.log("欢迎使用")
    }
}
// 实例化对象
let lenovo = new Computer("lenovo", 5499);
console.log(lenovo)
lenovo.start();

class中的静态成员,属于类而不属于实例化对象

class Phone {
    // 静态属性
    static name = "手机"
// 静态方法
static call() {
    console.log("我能打电话");
	}
}

let huawei = new Phone;
console.log(huawei.name);//undifined
console.log(Phone.name);//手机
Phone.call();//我能打电话
huawei.call();//huawei.call is not a function

使用构造函数实现继承

//父类对象
class Phone {
    constructor(brand, price) {
        this.brand = brand;
        this.price = price;
    }
    call() {
        console.log("打电话");
    }
}
// 子类继承父类
class SmartPhone extends Phone {
    constructor(brand, price, color, size) {
        super(brand, price);
        this.color = color;
        this.size = size;
    }
    photo() {
        console.log("拍照");
    }
    playGame() {
        console.log("玩游戏");
    }
    // 子类重写父类的方法
    call() {
        console.log("视频通话");
    }
}

const xiaomi = new SmartPhone("小米6", 1999, "白色", "5.15inch");
console.log(xiaomi);
// 子类不能调用父类的同名方法
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();

class中get和set方法

class Phone{
    // get对动态属性进行封装
    get price (){
        console.log("get方法被执行");
        return "get get get"
    }
    // set属性可以进行属性的判断和封装,需要设置形参
    set price (newVal){
        console.log("set方法执行");
        console.log("新的价格为" + newVal);
    }
}
let p = new Phone();
console.log(p.price);
p.price = 100;

十八、数值扩展

  1. Number. EPSILON是 JavaScript表示的最小精度EPSILON属性的值接近于2.2264466492503136884726361816E-16多用于浮点数运算,用于解决浮点数计算误差问题
function equals(a, b) {
    if (Math.abs(a - b) < Number.EPSILON) {
        return true;
    } else {
        return false;
    }
}
console.log(0.1 + 0.2 === 0.3);
console.log(equals(0.1 + 0.2, 0.3));
  1. 二进制和八进制
let b = 0b1010;//二进制
let o = 0177;//八进制
let d = 0x123;//16进制
console.log(b);
console.log(o);
console.log(d);
  1. Number.isFinite检测一个数值是否为有限数
console.log(Number.isFinite(100));//true
console.log(Number.isFinite(100/0));//false
  1. Number.isNaN检测一个数值是否为NaN
console.log(Number.isNaN(2));//false
console.log(Number.isNaN(NaN));//true
  1. Number.parseInt Number.parserFloat字符串转整数
console.log(Number.parseInt("1323.1dcsdcd"));//1323
console.log(Number.parseFloat("13231.12dcsdcd"));//13231.12
  1. Number.isInteger判断一个数是否为整数
console.log(Number.isInteger(213.3));//false
console.log(Number.isInteger(213));//true
  1. Math.trunc将数字的小数部分抹掉
console.log(Math.trunc(12.3));
  1. Math.sign判断一个数到底为正数 负数 还是零
console.log(Math.sign(10));//1
console.log(Math.sign(0));//0
console.log(Math.sign(-10));//-1

十九、对象方法扩展

  1. Object.is 判断两个值是否完全相等,类似于=== 但是可以判断NaN是否相等
console.log(Object.is(110,110));//true
console.log(Object.is(110,10));//false
console.log(Object.is(NaN,NaN));//true
console.log(NaN === NaN);//false
  1. Object.assign 对象的合并
const config1 = {
    host: "127.0.0.1",
    port:"3306",
    user: "user",
    password: "123456",
    test: "test"
}
const config2 = {
    host: "49.123.124.5",
    port:"3306",
    user: "root",
    password: "root",
    enviroment: "dev"
}
console.log(Object.assign(config1,config2));

  1. Object.setPrototypeof Object.getPrototypeof
const school = {
    name: "SDUT"
}
const city = {
    student: ["山东", "河北", "内蒙", "贵州", "杭州"]
}

Object.setPrototypeOf(school, city);
console.log(Object.getPrototypeOf(school));
console.log(school);

二十、ES6的模块化

模块化:将大的程序文件,拆分成很多小的文件(模块),然后将小的文件组合起来

好处:防止命名冲突 代码复用 便于维护.

ES6模块化语法:

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

export命令用于规定模块的对外接口

Import命令用于输入其他模块提供的功能

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ES6模块化测试</title>
</head>

<body>
    <!-- 标签引入m1.js模块 -->
    <script type="module">
        //1.通用导入方式
        // 引入m1.js模块
        import * as m1 from "./js/m1.js";
        console.log(m1);
        console.log(m1.learn());
        // 引入m2.js模块
        import * as m2 from "./js/m2.js";
        console.log(m2);
        console.log(m2.study());
        // 引入m3.js模块
        import * as m3 from "./js/m3.js";
        console.log(m3);
        m3.default.change();

        //2.解构赋值
        import {name,learn} from "./js/m1.js";
        console.log(name);
        console.log(learn);
        // as使用别名的方式应用
        import{name as lisi,study} from "./js/m2.js";
        console.log(lisi);
        console.log(study);
        // 引入默认暴露
        import {default as m3} from "./js/m3.js";
        console.log(m3);

        //3.简便形式,只针对默认暴露
        import m3 from "./js/m3.js";
        console.log(m3);
    </script>
    <!-- 外部引入模块 -->
    <script src="./js/app.js" type="module"></script>
</body>

</html>
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » ES6语法规范