JavaScript模块化-ES Module

导读:本篇文章讲解 JavaScript模块化-ES Module,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

ESModule

ESModule基本使用

JavaScript没有模块化一直是它的痛点font>,所以才会产生我们前面学习的社区规范:CommonJS、AMD、CMD等,所以在ECMA推出自己的模块化系统时,大家也是非常兴奋。

ES Module和CommonJS的模块化有一些不同之处

  • 一方面它使用了importexport关键字;
  • 另一方面它采用编译期的静态分析,并且也加入了动态引用的方式

ES Module模块采用export和import关键字来实现模块化

  • export负责将模块内的内容导出
  • import负责从其他模块导入内容;

了解:采用ES Module将自动采用严格模式:use strict


注意: 如果直接在浏览器中运行代码,会报错, 这个报错在MDN上面有给出解释

  • https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Modules
  • 你需要注意本地测试 — 如果你通过本地加载Html 文件 (比如一个 file:// 路径的文件), 你将会遇到 CORS 错误,因为Javascript 模块安全性需要;
  • 你需要通过一个服务器来测试

我这里使用的VSCode插件:Live Server


在代码中看一下ES Module的基本使用吧:

  • script标签引入需要加上type='module', 表示是一个模块
<script src="./main.js" type="module"></script>
<script src="./foo.js" type="module"></script>
  • 注意: 导出的大括号不是一个对象, 他是一个固定的格式, 导出写的是标识符, 不是对象的增强写法;
  • 导出格式export { 标识符1, 标识符2, ... }
const name = "kaisa"
const age = 18

function running() {
  console.log("running~")
}

// 导出
export {
  name,
  age,
  running
}
  • main中导入文件
import { name, age, running } from "./foo.js";

console.log(name)
console.log(age)
running()

export其他用法

export关键字将一个模块中的变量、函数、类等导出;


我们希望将其他中内容全部导出,它可以有如下的方式

方式一(刚刚讲过)将所有需要导出的标识符,放到export后面的 {}中

  • 注意:这里的 {}里面不是ES6的对象字面量的增强写法,{}也不是表示一个对象的;

  • 所以: export {name: name},是错误的写法;

方式二: 导出时给标识符起一个别名

  • 通过as关键字起别名
  • 假如我们想要导出一个name属性, 而导入的地方已经定义过name属性, 那么我们可以为name属性取一个别名
export {
	// 导出时给fname取别名
  name as fname,
  age,
  running
}

方式三: 在语句声明的前面直接加上export关键字

  • 这种方式适用于, 当我们定义变量时, 就确定要导出的情况
  • 这种方式不可以取别名
// 定义变量的时候就导出
export const address = "成都市"

import其他用法

import关键字负责从另外一个模块中导入内容

导入内容的方式也有多种

方式一(刚刚讲过)import {标识符列表} from ‘模块’

  • 注意:这里的{}也不是一个对象,里面只是存放导入的标识符列表内容;

方式二:导入时给标识符起别名

  • 通过as关键字起别名
// 导入的时候取别名
import { name as fname, age, running, address } from "./foo.js";

方式三:通过 * 将整个模块全部导入, 并给整个模块取个别名

// 导入整个模块, 并取名为foo
import * as foo from "./foo.js"

// 使用模块内容
console.log(foo.name) // kaisa
console.log(foo.age) // 18
foo.running() // running~
console.log(foo.address) // address

export和import结合

补充:export和import可以结合使用

为什么要这样做呢?

  • 在开发和封装一个功能库时,通常我们希望将暴露的所有接口放到一个文件中;

  • 这样方便指定统一的接口规范,也方便阅读;

  • 这个时候,我们就可以使用export和import结合使用;

使用方法:

  • 例如想要从另一个文件导出, 再导出暴露出去
// 从其他文件导入
import { name, age, running, address } from "./foo.js"

// 导出
export {
  name,
  age,
  running,
  address
}
  • 优化方式一: 可以结合起来使用, 这样优化阅读性比较好(推荐)
export { name, age, running, address } from "./foo.js"
  • 优化方式二: 阅读性比较差, 代码更简介
export * from "./foo.js"

default用法

前面我们学习的导出功能都是有名字的导出(named exports):

  • 在导出export时指定了名字;

  • 在导入import时需要知道具体的名字;

还有一种导出叫做默认导出(default export)

  • 默认导出export时可以不需要指定名字

  • 导入时不需要使用 {},并且可以自己来指定名字

  • 它也方便我们和现有的CommonJS等规范相互操作;

演示代码:

  • 默认导出
export default function() {
  console.log("foo函数~")
}
  • 导入时, 由于默认导出是没有名字的, 所以我们可以自定义名称
// 导入可自定义名, 且不需要加大括号{}
import aaa from "./foo.js"

aaa()

注意:在一个模块中,只能有一个默认导出(default export);

import函数

通过import加载一个模块,是不可以在其放到逻辑代码中的,比如:

let flag = true

if (flag) {
  // 错误示范
  import { name, age, running } from "./foo.js"
}

为什么会出现这个情况呢?

  • 这是因为ES Module在被JS引擎解析时,就必须知道它的依赖关系

  • 由于这个时候js代码没有任何的运行,所以无法在进行类似于if判断中根据代码的执行情况

  • 甚至拼接路径的写法也是错误的:因为我们必须到运行时能确定path的值

但是某些情况下,我们确确实实希望动态的根据条件判断, 来决定示范加载某一个模块

  • 如果根据不懂的条件,动态来选择加载模块的路径;
  • 这个时候我们需要使用 import() 函数来动态加载;
  • import函数中导入是异步的, 不会阻塞代码, 返回一个Promise,可以通过then获取结果;

演示代码:

let flag = true

if (flag) {
  // 会返回一个Promise
  import("./foo.js").then(res => {
    // 在then方法中获取结果
    console.log(res.name)
    console.log(res.age)
    res.running()
  })
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/120099.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!