学习笔记:ECMAScript教程(尚硅谷)

介绍

  • 本文主要记录在学习尚硅谷的 ECMAScript 课程时的一些笔记
  • 尚硅谷前端学科全套课程请点击这里进行下载,提取码:afyt

一、ECMA

  • ECMA-262 历史版本点击这里查看
  • ES6 兼容性点击这里查看

二、ES6

1.let

  • 变量不能重复声明

    1
    2
    let name = "wrysmile"
    let name = "Wrysmile"
  • 块级作用域

    • 在ES5中只有全局、函数、eval(严格模式下才有)作用域
    • ES6新增块级作用域,let 声明的变量只能作用在块级作用域中
    • if、else、while、for、花括号都属于块级作用域
  • 不存在变量提升

  • 不影响作用域链

!案例:遍历绑定事件时使用不使用this

  • 在遍历绑定事件时
    • 如果使用 var 声明,不使用 this 时会因为全局作用域中的变量导致事件找不到当前下标
    • 如果使用 let 声明,因为其声明的变量只在其块级作用域中有效,所以事件可以找到当前下标
  • 案例如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <h1>点击切换颜色</h1>
    <div class="container">
    <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 (){
    items[i].style.background = "red";
    }
    }
    </script>

2.const

  • 作用:用来声明一个常量
  • 一定要赋初始值
  • 一般常量使用大写
  • 常量的值不能修改
  • 块级作用域
  • 对于数组和对象的元素修改,不算做常量的修改,不会报错

3.变量解构赋值

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

  • 数组的解构:

    1
    2
    3
    const arr = ["小明","小张","小王","小李"];
    let [a,b,c,d] = arr;
    console.log(a,b,c,d);
  • 对象的解构:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const obj = {
    name: "Wrysmile",
    age: 25,
    eat: function (){
    console.log("我爱吃西瓜");
    }
    }
    let {name, age , eat} = obj;
    console.log(name,age,eat);
    eat();

4.模板字符串

  • 概念:ES6 中引入了新的声明字符串的方式

  • 内容中可以直接出现换行符

    1
    2
    3
    4
    let str = `你好
    你好
    你好`;
    console.log(str);
  • 支持变量拼接,只需要使用 ${} 即可进行拼接

    1
    2
    3
    let str1 = "陈奕迅";
    let str2 = `${str1}是我最喜欢的歌手`;
    console.log(str2);

5.简化对象写法

  • ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    let name = "Wrysmile";
    let age = 25;
    let change = function (){
    console.log("改变");
    }
    const person = {
    name,
    age,
    change,
    improve(){
    console.log("提高");
    }
    }

6.箭头函数

  • ES6 中允许使用箭头来定义函数

  • 特性:

    • this 是静态的,this 始终指向函数声明时所在作用域下的 this 的值
    • 不能作为构造函数来实例化对象
    • 不能使用 arguments 变量
  • 简写:

    • 省略小括号:当形参有且只有一个的时候
    • 省略花括号:当代码体只有一条语句的时候,此时代码体的 return 必须省略,因为语句的执行结果就是函数的返回值
  • 适合:

    • 与 this 无关的回调,如定时器,数组的方法回调
  • 不适合:

    • 与 this 有关的回调,如事件回调,对象的方法

案例

  • 通过静态this来修改元素属性

    1
    2
    3
    4
    5
    6
    const ad = document.getElementById("ad");
    ad.addEventListener("click", function (){
    setTimeout(() => {
    this.style.background = "pink";
    },2000)
    })
  • 从数组中返回偶数的元素

    1
    2
    3
    4
    5
    6
    const arr = [1,4,6,7,58,63,100];
    const newArr = arr.filter(function (item){
    return item % 2 === 0;
    })
    const newArr2 = arr.filter(item => item %2 === 0);
    console.log(newArr, newArr2);

7.函数参数的默认值

  • ES6 允许给函数参数赋值初始值
  • 特性:
    • 形参初始值,具有默认值的参数,一般位置要靠后
    • 可以与解构赋值结合
  • 与解构赋值结合可以省略一部分重复代码,如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function connect(options){
    console.log(options.host, options.username, options.password, options.port);
    }
    function connect({host="127.0.0.1", username, password, port}){
    console.log(host, username, password, port);
    }
    connect({
    host: "www.wrysmile.cn",
    username: "admin",
    password: "admin",
    port: 3306
    })

8.rest 参数

  • ES6 可以使用 rest 参数来获取函数的实参,用来代替 arguments

  • 语法:...args,即在标识符前加三个点

    1
    2
    3
    4
    5
    6
    7
    function date(...args){
    console.log(args);
    }
    function date(a, b, ...args){
    console.log(args)
    }
    date(1, 2, 3, 9);
  • 与 arguments 的区别:

    • arguments 返回的是对象
    • rest 参数返回的是数组

9.扩展运算符

  • ... 能将数组转换为逗号分割的参数序列,如下:

    1
    2
    3
    4
    5
    6
    const tfboys = ["易烊千玺", "王源", "王俊凯"];
    function chunwan(){
    console.log(arguments);
    }
    chunwan(tfboys);
    chunwan(...tfboys);
  • 两个函数执行结果对比如下:
    es01.png

  • 应用:

    • 数组的合并
    • 数组的克隆
    • 伪数组转为真正的数组
  • 应用案例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 数组的合并
    const kuaizi = ["王太利", "肖央"];
    const fenghuangchuanqi = ["曾毅", "玲花"];
    const songer = [...kuaizi, ...fenghuangchuanqi];
    console.log(songer);
    // 数组的克隆
    const sanzhihua = ["E","G","M"];
    const sanyecao = [...sanzhihua];
    console.log(sanyecao);
    // 将伪数组转为真正的数组
    const divs = document.querySelectorAll("div");
    const divArr = [...divs]
    console.log(divs);
    console.log(divArr);

10.Symbol

  • ES6 中引入了一种新的原始数据类型 Symbol,表示独一无二的值
  • 它是 JS 的第七种数据类型,也是一种类似于字符串的数据类型
  • 特点:
    • Symbol 的值是唯一的,用来解决命名冲突的问题
    • Symbol 的值不能与其他数据进行运算
    • Symbol 定义的对象属性不能使用 for...in 循环遍历,但是可以使用 Reflect.ownKeys 来获取对象的所有键名

(1).基础使用

  • 普通创建 Symbol:

    1
    let s = Symbol();
  • 使用 Symbol.for() 来创建 Symbol:(可以通过描述字符串来找到唯一的Symbol值)

    1
    let s1 = Symbol.for("s1");
  • 使用描述字符串来标识一个 Symbol:

    1
    let s2 = Symbol("s2");

(2).创建对象属性

  • 当向某个对象中添加方法时,为了避免重名的问题,可以使用 Symbol 来唯一标识
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    let game = {
    name: "俄罗斯方块",
    up: function (){
    console.log("向上");
    },
    down: function (){
    console.log("向下");
    }
    }
    let methods = {
    up: Symbol(),
    down: Symbol()
    }
    game[methods.up] = function (){
    console.log("唯一的向上");
    }
    game[methods.down] = function (){
    console.log("唯一的向下");
    }
    console.log(game);

(3).Symbol 内置值

  • 除了定义自己使用的 Symbol 值以外,ES 6还提供了11个内置的 Symbol 值,指向语言内部使用的方法
  • 视频链接点这里的p17

11.迭代器

  • 迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署了 Iterator 接口就可以完成遍历操作
  • ES6 创造了一种新的遍历命令 for...of 循环,而迭代器主要供 for...of 消费
    • for...in 循环是获取到了属性名
    • fro...of 循环是获取到了属性值
  • 原生具备 Iterator 接口的数据,即可以使用 for...of 循环的有:Array、Arguments、Set、Map、String、TypedArray、NodeList
  • 工作原理:
    • 创建一个指针对象,指向当前数据结构的起始位置
    • 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
    • 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
    • 每调用 next 方法返回一个包含 value 和 done 属性的对象
      1
      2
      3
      const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
      let iterator = xiyou[Symbol.iterator]();
      console.log(iterator.next());
  • 注意:需要自定义遍历数据的时候,要想到迭代器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    // 自定义迭代器 —— 遍历得出对象中数组的每个值
    const classNum = {
    name: "云计算一班",
    stus: [
    '小明',
    '小黄',
    '小红'
    ],
    [Symbol.iterator](){
    // 索引变量
    let index = 0;
    // 保存this
    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 (let v of classNum){
    console.log(v);
    }

12.生成器

  • ES6 提供了一种异步编程的解决方案 —— 生成器函数

  • 异步编程指纯回调函数,例如:Node中的fs模块、ajax、MongoDB等

  • 创建生成器:在函数名前面加一个星号,返回的是迭代器对象,所以需要使用 next() 方法来执行其中的语句

    1
    2
    3
    4
    5
    function * gen(){
    console.log("hello");
    }
    let iterator = gen();
    iterator.next();
  • 代码分割:在该函数中可以使用 yield 来进行代码分割,执行 next() 方法时就会按分割的区域顺序执行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function * gen(){
    console.log("111");
    yield "第一条分割线";
    console.log("222");
    yield "第二条分割线";
    console.log("333");
    yield "第三条分割线";
    console.log("444");
    }
    let iterator = gen();
    iterator.next();
    iterator.next();
    iterator.next();
    iterator.next();
  • 函数传参:在 next() 方法中可以传入实参,该实参将作为上一次 yield 语句的返回值来进行展示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function * gen2(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 iterator2 = gen2("AAA");
    console.log(iterator2.next());
    console.log(iterator2.next("BBB"));
    console.log(iterator2.next("CCC"));
    console.log(iterator2.next("DDD"));

案例:

  • 1秒后输出111,2秒后输出222,3秒后输出333

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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();
  • 模拟获取用户数据、订单数据、商品数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    function getUser(){
    setTimeout(() => {
    let data = "用户数据";
    iterator.next(data);
    }, 1000)
    }
    function getOrder(){
    setTimeout(() => {
    let data = "订单数据";
    iterator.next(data);
    }, 1000)
    }
    function getGoods(){
    setTimeout(() => {
    let data = "商品数据";
    iterator.next(data);
    }, 1000)
    }
    function * gen(){
    let user = yield getUser();
    console.log(user);
    let order = yield getOrder();
    console.log(order);
    let goods = yield getGoods();
    console.log(goods);
    }
    let iterator = gen();
    iterator.next();

13.Promise

  • ES6 引入的一种新的异步编程解决方案,是一个构造函数

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const p = new Promise(function (resolve, reject){
    let data = "数据库中的数据";
    // resolve(data);
    let err = "错误的数据";
    reject(err);
    });
    p.then(function (value){
    console.log(value);
    }, function (reason){
    console.log(reason);
    })
  • then() 方法:该方法的返回结构是 Promise 对象,对象状态由回调函数的执行结构来决定

    • 如果回调函数中返回的结构是非 Promise 类型的属性,返回状态为成功,返回值为对象的成功的值
    • 如果回调函数中返回的结构是 Promise 类型的属性,返回状态是成功则成功,失败则失败
    • 如果回调函数中返回的结构是抛出错误,返回状态为失败
    • 所以,then() 方法可以链式调用
  • catch() 方法:是 then() 方法的语法糖,具体同上

案例:

  • 使用 Promise 读取一个文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    const fs = require("fs");
    // 普通读取一个文件
    fs.readFile("./file/test.md", (err,data) => {
    if (err) throw err;
    console.log(data.toString());
    })
    // Promise读取一个文件
    const p = new Promise((resolve, reject) => {
    fs.readFile("./file/test.md", (err, data) => {
    if(err) reject(err);
    resolve(data);
    })
    });
    p.then((value) => {
    console.log(value.toString());
    }, (reason) => {
    console.log(reason);
    })
  • 使用 Promise 封装 AJAX:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    const p = new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", "http://127.0.0.1:9000/data");
    xhr.send();
    xhr.onreadystatechange = function (){
    if (xhr.readyState === 4){
    if (xhr.status >= 200 && xhr.status < 300){
    resolve(xhr.response);
    }else {
    reject(xhr.response);
    }
    }
    }
    });
    p.then(value => {
    console.log(value);
    }, reason => {
    console.error(reason);
    })
  • 使用 Promise 读取多个文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 普通读取多个文件
    fs.readFile("./file/test1.md",(err,data1) => {
    fs.readFile("./file/test2.md", (err,data2) => {
    console.log(data1 + "\r\n" + data2);
    })
    })
    // Promise读取多个文件
    const p = new Promise((resolve, reject) => {
    fs.readFile("./file/test1.md", (err,data) => {
    resolve(data);
    })
    });
    p.then(value => {
    return new Promise((resolve, reject) => {
    fs.readFile("./file/test2.md", (err,data) => {
    resolve([value, data]);
    })
    });
    }).then(value => {
    console.log(value.join("\r\n"));
    })

14.Set

  • ES6 提供了新的数据结构 —— Set(集合),类似于数组但成员的值都是唯一的,数据类型是对象

  • 集合实现了 Iterator 接口,所以可以使用 扩展运算符for...of 来进行遍历

  • 声明一个 set,同时在传入值的时候还可以达到数组去重的效果

    1
    2
    3
    4
    const s1 = new Set();
    console.log(s1);
    const s2 = new Set([1,2,3,4,3,2,1]);
    console.log(s2)
  • 集合的属性和方法:

    • s.size():返回集合的元素个数
    • s.add():增加一个新元素,返回当前集合
    • s.delete():删除一各元素,返回布尔值
    • s.has():检测集合中是否包含某个元素,返回布尔值
    • s.clear():清空当前集合

案例:

  • 数组去重:

    1
    2
    3
    const arr = [1, 2, 4, 6, 4, 1];
    const s = new Set(arr);
    console.log([...s]);
  • 两数组的交集

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    const arr1 = [1, 2, 4, 6, 4, 1];
    const arr2 = [5, 6, 6, 5];
    const sArr1 = new Set(arr1);
    const sArr2 = new Set(arr2);
    const result = [...sArr1].filter(item => {
    if (sArr2.has(item)){
    return true;
    }else {
    return false;
    }
    })
    const result1 = [...sArr1].filter(item => sArr2.has(item));
    console.log(result, result1);
  • 两数组的并集

    1
    2
    3
    4
    const arr1 = [1, 2, 4, 6, 4, 1];
    const arr2 = [5, 6, 6, 5];
    const result = [...new Set([...arr1,...arr2])];
    console.log(result);
  • 两数组的差值

    1
    2
    3
    4
    5
    6
    7
    const arr1 = [1, 2, 4, 6, 4, 1];
    const arr2 = [5, 6, 6, 5];
    const sArr1 = new Set(arr1);
    const sArr2 = new Set(arr2);
    const se = [...sArr1].filter(item => !(sArr2.has(item)));
    const desc = [...sArr2].filter(item => !(sArr1.has(item)));
    console.log(se, desc);

15.Map

  • ES6 提供了 Map 数据结构,类似于对象,是键值对的集合,但键不限于字符串,各种类型的值(包括对象)都可以当做键

  • Map 也实现了 Iterator 接口,所以可以使用 扩展运算符for...of 来进行遍历

  • 声明一个 Map:

    1
    2
    3
    const m = new Map();
    m.set("name","Wrysmile");
    console.log(m);
  • Map 的属性和方法:

    • m.size():返回 Map 的元素个数
    • m.set():增加一个新元素,返回当前 Map
    • m.get():返回键名对象的键值
    • m.has():检测 Map 中是否包含某个元素,返回布尔值
    • m.clear():清空集合,返回 undefined

16.Class

  • 通过 class 关键字可以定义类,可以看做一个语法糖

(1).声明类

  • 如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Phone{
    // 构造方法,语法固定不可修改
    constructor(phone, price) {
    this.phone = phone;
    this.price = price;
    }
    // 不能使用 ES5 的对象完整形式
    call(){
    console.log("我可以打电话");
    }
    }
    const onePlus = new Phone("一加",2999);
    console.log(onePlus);

(2).静态成员

  • 通过 static 关键字设置的属性为静态属性,是不能被实例对象所引用的。就类似于 Phone.name 设置的属性
  • 而不通过 static 关键字设置的属性是可以被实例对象所调用的。就类似于 Phone.prototype.name 设置的属性

(3).继承

  • ES5 中的对象继承:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // 父类
    function Phone(brand, price){
    this.brand = brand;
    this.price = price;
    }
    Phone.prototype.call = function (){
    console.log("我可以打电话");
    }
    // 子类
    function SmartPhone(brand, price, color, size){
    Phone.call(this, brand, price);
    this.color = color;
    this.size = size;
    }
    // 设置子类构造函数的原型
    SmartPhone.prototype = new Phone;
    SmartPhone.prototype.constructor = SmartPhone;
    // 声明子类的方法
    SmartPhone.prototype.photo = function (){
    console.log("我可以拍照片");
    }
    const onePlus = new SmartPhone("一加", 2999, "黑色", "6.6inch");
    console.log(onePlus);
  • ES6 中的对象继承:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // 父类
    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("我可以拍照片");
    }
    }
    const onePlus = new SmartPhone("一加", 2999, "黑色", "6.6inch");
    console.log(onePlus);

(4).重写

  • 我们可以在子类中重写父类的同名方法,同时也可以使用 super.方法名() 来调用父类的方法:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    // 父类
    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;
    }
    call(){
    super.call();
    console.log("我是子类的打电话");
    }
    photo(){
    console.log("我可以拍照片");
    }
    }
    const onePlus = new SmartPhone("一加", 2999, "黑色", "6.6inch");
    console.log(onePlus);

(5).get与set

  • 在 Class 中可以使用 get 来读取类中的方法,同时还可以读取到返回值

    1
    2
    3
    4
    5
    6
    7
    8
    class Phone{
    get call(){
    console.log("call方法被调用了");
    return "get到的";
    }
    }
    const p = new Phone();
    console.log(p.call);
  • 在 Class 中给方法赋值时就会调用 set 中的函数

    1
    2
    3
    4
    5
    6
    7
    class Phone{
    set call(arg){
    console.log("set中的方法被调用了");
    }
    }
    const p = new Phone();
    p.call = "flag";

17.数值扩展

  • Number.EPSILON:JS 中表示的最小精度,其值接近于 2.22*10(-16方)
  • 进制数定义:
    • 二进制:0b1010
    • 八进制:0o777
    • 十进制:100
    • 十六进制:0xff
  • Number.isFinite:检测一个数值是否为有限数
  • Number.isNaN:检测一个数值是否为 NaN
  • Number.parseInt/Float:将字符串转为整数/浮点数
  • Number.isInteger:判断一个数是否为整数
  • Math.trunc:将数字的小数部分抹掉
  • Math.sign:判断一个数到底为整数、负数还是零

18.对象方法扩展

  • Object.is:判断两个值是否完全相等
  • Object.assign(oldObject, newObject):对象的合并,当旧对象中有新对象中没有的时候,会进行合并,否则会直接覆盖
  • Object.setPrototypeOf:设置原型对象(不推荐使用)
  • Object.getPrototypeOf:获取原型对象(不推荐使用)

19.模块化

  • 是指将一个大的程序文件拆成许多小的文件,然后进行组合
  • 优势:
    • 防止命名冲突
    • 代码复用
    • 高维护性
  • 模块化规范产品:
    • CommonJS:NodeJS、Browserify
    • AMD:requireJS
    • CMD:seaJS

(1).暴露与引入

  • 暴露模块内容的方法:
    • 在每一个需要暴露的变量或方法前面都加一个 export
    • 也可以暴露一个对象,将需要暴露的变量或方法都放入对象中
    • 也可以使用 export default xxx 来进行默认暴露的设置
  • 通过 <script> 标签来引入模块的方法:
    • 通用的引入:import * as xxx from "./test.js"
    • 解构赋值的引入,以下三个分别对应暴露模块的三种形式:
      • import {school} from "./test.js"
      • import {school as guigu} from "./test.js"
      • import {default as a} from "./test.js"
    • 简便形式的引入,只针对于默认暴露的方法:import b from "./test.js"
  • 通过 <script> 标签的 src 属性来引入:
    • 在 src 中引入某个js文件
    • 然后在该 js 文件中直接使用上面语句进行引入

(2).babel代码转换

  • 通过使用 babel 可以将 ES6语法转换为 ES5语法,方便不同浏览器的使用,官网点击这里
  • 使用方法:
    • 使用 npm init --yes 进行初始化
    • 使用 npm i babel-cli babel-preset-env browserify -D 命令来安装相关的开发依赖,会安装babel-cli(命令行工具)、babel-preset-env(预设包,进行转换)、browserify(打包工具)这三个工具
    • 使用 npx babel 原始路径 -d 新路径 命令来进行转换
    • 使用 npm browserify 新路径下的配置文件 -o 新路径配置文件 命令来进行打包
    • 网页中只要引用最后打包好的文件即可