JavaScript中的模块化开发

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: JavaScript中的模块化开发

js中的模块化开发

模块设计

  • 模块就是一个独立的文件,里面是函数或者类库
  • 虽然 JS 没有命名空间的概念,使用模块可以解决全局变量冲突
  • 模块需要隐藏内部实现,只对外开发接口
  • 模块可以避免滥用全局变量,造成代码不可控
  • 模块可以被不同的应用使用,提高编码效率

标签使用

在浏览器中使用以下语法靠之脚本做为模块使用,这样就可以在里面使用模块的代码了。

在 html 文件中导入模块,需要定义属性 type="module"

<script type="module"></script>

模块路径

在浏览器中引用模块必须添加路径如./ ,但在打包工具如webpack中则不需要,因为他们有自己的存放方式。

测试的 dd.js 的模块内容如下

export let dd = {
  name: "dd"
};

使用需要添加上路径

<script type="module">
  import { dd } from "./dd.js";
</script>

延迟解析

模块总是会在所有 html 解析后才执行,下面的模块代码可以看到后加载的 button 按钮元素。

  • 建议为用户提供加载动画提示,当模块运行时再去掉动画
<body>
  <script type="module">
    console.log(document.querySelector("button")); //Button
  </script>
  <script>
    console.log(document.querySelector("button")); //undefined
  </script>
  <button>后盾人</button>
</body>

作用域

模块都有独立的顶级作用域,下面的模块不能互相访问

<script type="module">
  let hd = "houdunren.com";
</script>

<script type="module">
  alert(hd); // Error
</script>

单独文件作用域也是独立的,下面的模块 1.2.js 不能访问模块 1.1.js 中的数据

<script type="module" src="1.1.js"></script>
<script type="module" src="1.2.js"></script>

文件内容如下
# 1.1.js
let hd = "houdunren";

# 1.2.js
console.log(hd)

预解析

模块在导入时只执行一次解析,之后的导入不会再执行模块代码,而使用第一次解析结果,并共享数据。

  • 可以在首次导入时完成一些初始化工作
  • 如果模块内有后台请求,也只执行一次即可

导入导出

ES6 使用基于文件的模块,即一个文件一个模块。

  • 使用export 将开发的接口导出
  • 使用import 导入模块接口
  • 使用*可以导入全部模块接口
  • 导出是以引用方式导出,无论是标量还是对象,即模块内部变量发生变化将影响已经导入的变量

导出模块

使用 export 导出模块接口,没有导出的变量都是模块私有的。

具名导入

import { User, site, func } from "./hd.js";

批量导入(不建议)

如果要导入的内容比较多,可以使用 * 来批量导入。

<script type="module">
  import * as api from "./hd.js";
  console.log(api.site);
  console.log(api.User);
</script>

别名

使用 as 对接口重命名

导入别名

import { User as user, func as action, site as name } from "./hd.js";

导出别名

export { site as ss, func as ff, User };

默认导出

很多时候模块只是一个类,也就是说只需要导入一个内容,这地可以使用默认导入。

使用default 定义默认导出的接口,导入时不需要使用 {}

  • 可以为默认导出自定义别名
  • 只能有一个默认导出
  • 默认导出可以没有命名

单一导出

下面是hd.js 模块内容,默认只导出一个类。并且没有对类命名,这是可以的

export default class {
  static show() {
    console.log("User.method");
  }
}

从程序来讲如果将一个导出命名为 default 也算默认导出

class User {
  static show() {
    console.log("User.method");
  }
}
export { User as default };

导入时就不需要使用 {} 来导入了

<script type="module">
  import User from "./hd.js";
  User.show();
</script>

默认导出的功能可以使用任意变量接收

<script type="module">
  import hd from "./hd.js";
  hd.show();
</script>

混合导出

模块可以存在默认导出与命名导出。

使用export default 导出默认接口,使用 export {} 导入普通接口

const site = "后盾人";
const func = function() {
  console.log("is a module function");
};
export default class {
  static show() {
    console.log("user.show");
  }
}
export { site, func };

也可以使用以下方式导出模块

const site = "后盾人";
const func = function() {
  console.log("is a module function");
};
class User {
  static show() {
    console.log("user.show");
  }
}
export { site, func, User as default };

导入默认接口时不需要使用 {} ,普通接口还用 {} 导入

<script type="module">
    //可以将 hd 替换为任何变量
  import hd from "./hd.js";
  import { site } from "./hd.js";
  console.log(site);
  hd.show();
</script>

可以使用一条语句导入默认接口与常规接口

import show, { name } from "/modules/houdunren.js";

也可以使用别名导入默认导出

import { site, default as hd } from "./hd.js";
console.log(site);
hd.show();

如果是批量导入时,使用 default 获得默认导出

<script type="module">
  import * as api from "./hd.js";
  console.log(api.site);
  api.default.show();
</script>

使用建议

对于默认导出和命名导出有以下建议

  • 不建议使用默认导出,会让开发者导入时随意命名

    import hd from "./hd.js";
    import xj from "./hd.js";
  • 如果使用默认导入最好以模块的文件名有关联,会使用代码更易阅读

    import hd from "./hd.js";

导出合并

解决问题

可以将导入的模块重新导出使用,比如项目模块比较多,这时可以将所有模块合并到一个入口文件中。

这样只需要使用一个模块入口文件,而不用关注多个模块文件

//demo.js
import * as gg from './dd.js'
import * as mm from './mm.js'
export {gg, mm};
<script type="module">
  import * as demo from './demo.js';
  demo.gg.show(); 
</script>

动态加载

使用 import 必须在顶层静态导入模块,而使用import() 函数可以动态导入模块,它返回一个 promise 对象。

下面是在点击事件发生后按需要加载模块

<button>后盾人</button>
<script>
  document.querySelector("button").addEventListener("click", () => {
    let hd = import("./hd.js").then(({ site, func }) => {
      console.log(site);
    });
  });
</script>
相关文章
|
4月前
|
JavaScript 前端开发
如何使用 JavaScript 实现模块化开发?
如何使用 JavaScript 实现模块化开发?
19 1
|
18天前
|
缓存 JavaScript 前端开发
JavaScript模块化开发:ES6模块与CommonJs的对比与应用
JavaScript模块化开发:ES6模块与CommonJs的对比与应用
17 2
|
4月前
|
缓存 前端开发 JavaScript
Javascript模块化开发基础,最新美团点评前端团队面试题
Javascript模块化开发基础,最新美团点评前端团队面试题
|
4月前
|
JavaScript 前端开发
在JavaScript中实现模块化开发有多种方法
【5月更文挑战第10天】JavaScript模块化开发可通过CommonJS、AMD和ES6模块实现。CommonJS适用于服务器端,使用`require`和`module.exports`处理模块;AMD(如RequireJS)用于浏览器端,依赖`require`和`define`;ES6模块提供原生支持,使用`import`和`export`。选择方式需考虑项目环境、复杂度和技术栈。
41 4
|
4月前
|
JavaScript 前端开发 测试技术
【JavaScript技术专栏】JavaScript模块化开发实践
【4月更文挑战第30天】JavaScript模块化开发缓解了大规模应用的复杂性,通过拆分为独立模块提升代码可维护性、可读性和可测试性。CommonJS在Node.js中用于服务器,而AMD(RequireJS)适合浏览器的异步加载。ES6模块结合两者优点,提供原生支持。实践时遵循单一职责、命名规范和依赖管理等原则,借助Webpack、RequireJS等工具提升效率。模块化是现代JavaScript不可或缺的一部分,促进团队协作和代码复用。
50 0
|
4月前
|
JavaScript 前端开发
JavaScript的ES5模块化开发
JavaScript的ES5模块化开发
|
缓存 JavaScript 前端开发
[Node] Node.js JavaScrpt模块化开发
[Node] Node.js JavaScrpt模块化开发
|
4月前
|
JavaScript 前端开发
JavaScript高级主题:什么是模块化开发?CommonJS 和 ES6 模块的区别是什么?
JavaScript高级主题:什么是模块化开发?CommonJS 和 ES6 模块的区别是什么?
43 1
|
9月前
|
JavaScript 前端开发
【Node学习】—Node.js中模块化开发的规范
【Node学习】—Node.js中模块化开发的规范