模块化

110 阅读4分钟

模块化

把一类功能(方法)单独封装一个文件(模块),在使用的时候只需要引入需要的功能即可,以此来组合用来实现一些效果。

带来的问题:

  • JS 文件引入顺序
  • JS 文件之间相互依赖
  • JS 文件内部的变量会污染全局

不使用模块化

按照顺序引入 JS 文件

缺点:

  • 不利于维护,因为看不出以来了哪个文件
  • 全局变量污染
  • 依赖关系不清楚,例如:不知道 a.js 文件里面有没有引入 b.js 文件

IIFE(自执行函数) 伪模块化标准

语法:(function () {})()

使用:每个文件都作为独立模块,使所有内容都在自己的私有作用域里。因为外界无法使用,所以要把想要暴露的方法、变量以一个对象的形式挂载在 window 上。

(function () {
    // code write here ...
    
    // 要暴露的内容
    window.test = {
        key: value,
        key: value,
        ...
    }
})()

解决的问题:

  • 解决了依赖不清的问题
  • 解决了变量全局污染的问题

依赖的文件

(function (test) {
    // code write here ...
})(test)

存在的问题:

  • 文件顺序不能改动
  • 只知道依赖了哪些模块,但是不知道那些模块对应的文件

CommonJs 模块化标准

CommonJs 模块化标准是官方出版的,是 nodejs 伴生出来的,不能运行在浏览器环境,只能作为后端语言运行在 node 环境,但是可以经过打包处理运行在浏览器上。

语法:

const xxx = require('xxx') // 加载模块,得到的永远都是 module.exports 指向的对象

module.exports = xxx // 暴露模块,module 代表当前模块,它是一个对象,它的 exports 属性是对外的接口
// or
exports = xxx

模块在第一次加载后会被缓存,这就意味着多次调用require()不会导致模块的代码被执行多次,只会执行一次,从而提高了模块的加载效率。

AMD 模块化标准

AMD 是社区发行的非官方的模块化标准。

语法:

前提:使用 define() 需要在项目中引入 require.js 第三方文件

定义

define(function () {
    // code write here ...
    
    // 向外暴露方法或变量
    return {
        key: value,
        key: value,
        ...
    }
})

使用

define([依赖文件1, 依赖文件2, ...], function (依赖文件1暴露的对象, 依赖文件2暴露的对象, ...) {
    // code write here ...
})

最后整合为一个文件,使用的时候只需要引入这一个文件即可

define([依赖文件1, 依赖文件2, ...], function (依赖文件1暴露的对象, 依赖文件2暴露的对象, ...) {
    // code write here ...
})

解决的问题:

  • 解决了依赖不清的问题,既直到依赖的文件,也知道对应的模块
  • 解决了文件顺序问题,因为页面最后只引入一个整合过的文件
  • 解决了变量全局污染的问题,使用才会暴露 缺点:
  • 依赖前置,会先加载导入的依赖文件,执行完毕后才会往下执行自己的代码,导致首屏加载时间长
  • 缺点也是一个优点,后期操作流畅,因为依赖文件只会执行一次,然后缓存。

CMD 通用模块定义

CMD 也是社区发行的,非官方,是淘宝的一个人开发的,使用时必须要引入 sea.js 第三方文件。

语法:

define(function (require, exports, module) {
    // 导入
    var xxx = require('xxx') // 即时依赖,使用时才会执行
    
    // 导出
    exports.xxx = xxx
    
    // or
    module.exports = xxx
})

资源整合

seajs.use(['要依赖的文件'], function (模块) {}) // 前置依赖,先执行

解决的问题:

  • 依赖前置,实现了按需加载
  • 首屏加载快

缺点:

  • 操作不流畅

ESModule

ESModule 是 ES 语法自带的模块化标准,变成了 js 语法和关键字,不依赖第三方文件。

在页面中的 script 标签上书写 type="module"

语法:

import xxx from 'xxx' // 默认导入

export default xxx // 默认导出
import { xxx } from 'xxx' // 解构导入

export const xxx // 分别导出
import ('文件').then((接收文件导出的内容) => {}) // 按需加载

解决的问题:

  • 使用关键字,不依赖第三方文件
  • 每一个文件既可以做依赖文件,也可以做整合文件
  • 实现了按需加载