前端模块化(AMD,CMD,CommonJs,ES6)

本文探讨了前端模块化的发展历程,从最早的文件划分到命名空间、立即执行函数,再到AMD、CMD及CommonJS的不同实现方式,最后介绍ES6模块的特性与优势。对比各种模块化方法的优缺点,帮助开发者理解不同场景下的最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前端模块化

  • 将代码以功能区分,分成各个模块。

模块化演进过程

  • 最早期:以文件形式划分

    • 将js代码分成各个模块文件,以script src引入
    • 这种模式会带来很多问题:
      • -污染全局变量
      • 命名冲突
      • 无法管理模块依赖关系
      • 完全依靠约定
  • 第二阶段:命名空间方式

    • 将方法、变量用JavaScript Object包裹
  • 第三阶段: 使用立即执行函数包裹

    • 实现了私有成员的概念
    • 用立即执行函数的参数来表名依赖关系
  • 以上的形式 非常依赖手动加载模块,以及加载顺序

AMD

实现
  • 浏览器端 – require.js
说明
  • 依赖必须提前声明好
  • 模块加载异步,指定回调函数
基本语法
引入
//通过数组引入依赖,回调函数通过形参传入依赖
define(['Module1', ‘Module2’], function (Module1, Module2) {

    function foo () {
        /// someing
        Module1.test();
    }

    return {foo: foo}
});
优点

适合在浏览器环境中异步加载模块。可以并行加载多个模块

缺点

提高开发成本,不能按需加载,必须提前加载所有的依赖,使用相对复杂,模块js文件请求频繁

CMD

实现
  • 浏览器端 – sea.js
说明
  • 对于依赖的模块AMD是提前执行,CMD是延迟执行
  • AMD推崇依赖前置 CMD推崇依赖就近
  • 整合了commonjs和amd的特点
  • 模块的加载是异步的,模块使用时才会加载执行
基本语法
引入
define(function (require, exports, module) {
    
    //依赖可以就近书写
    var a = require('./a');
    a.test();
    
    ...
    //软依赖
    if (status) {
    
        var b = requie('./b');
        b.test();
    }
});

define(function(require,exports, module) {
	exports.xxx = value
    module.exports = value
})

define(function(require,exports, module) {
	var module2 = require('./module2')
    require.async('./module3', function(module3) 	{
    	......    
    })
    module.exports = value
})
优点

可以按需加载,依赖就近

缺点

依赖SPM打包,模块的加载逻辑偏重

COMMON.JS

实现
  • 服务端 – node
  • 浏览器 – webpack、browserfy
说明
  • 模块加载同步,资源加载完再执行
  • 每个文件都可以是一个模块
  • 服务端 模块加载时运行时同步加载
  • 浏览器 模块加载是提前编译打包处理
  • 对于基本数据类型,属于复制。会被模块缓存
  • 对于复杂数据类型 属于浅拷贝。由于两个模块引用 的对象指向同一个内存空间,值修改会影响另一个模块
  • 当使用require命令加载某个模块时,就会运行整个模块的代码
  • 当使用require加载同一个模块时,不会再执行该模块,就返回第一次执行的结果
  • 循环加载时,属于加载时执行
基本语法
// 引入模块
// 第三方
var fs = require('fs')

//自定义模块
require('./xxx,jpg')

//读入并执行一个js文件,然后返回该模块的exports对象,如果没有就会报错


//暴露模块
module.exports = value

exports.xxx = value

//module变量代表当前模块。这个变量是一个对象,它的exports属性是对外的接口

ES6 MODULE

实现
  • 服务端和浏览器通用
  • 浏览器端 — 目前需要Babel将es6转成es5、Browserfy编译
说明
  • 依赖需要提前声明 import在顶层
  • es6模块中的值属于 动态只读引用
  • 对于只读来说,不允许修改引入变量的值,当模块遇到import命令时就会生成一个只读引用,等到脚本真正执行时,再根据只读引用,到被加载的那个模块里面去取值
  • 对于动态来说,原始值发生变化,import加载的值也会发生变化,不论是什么类型
  • 循环加载时,ES6模块是动态引用,只要两个模块之间存在某个引用,代码就能执行
基本语法
//引入
import 

import xxx from 'xxx.js'
import {xxx} from 'xxx.js'
//暴露
export

export default module
export module
和commonjs的区别

es6输出的是只读引用、commonjs输出的是值的浅拷贝

因为commonjs加载的是一个对象,该对象只有在脚本运行完才会生成

es6不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值