博客
关于我
谈谈前端模块化的演变历程
阅读量:430 次
发布时间:2019-03-06

本文共 2758 字,大约阅读时间需要 9 分钟。

JavaScript模块化的发展历程

前言

JavaScript并非传统意义上的模块化编程语言,它本身不支持"类"(class)和"模块"(module)的概念。然而,随着前端开发的需求不断增长,对模块化的需求日益迫切。从最初的简单模块写法,到AMD和CMD规范的提出,再到ES6的发布,JavaScript模块化技术经历了显著的进步,现已能够在浏览器和服务器端方便地支持"类"和"模块"。

一、以前的写法

1. 原始写法

早期,开发者采用简单的函数形式编写模块:

function m1(){    //...  }  function m2(){    //...  }

然而,该写法存在明显缺陷:污染全局变量,模块成员间缺乏直接关系,难以管理和维护。

2. 对象写法

为了解决上述问题,开发者将模块写成一个对象形式:

var module1 = new Object({    _count : 0,    m1 : function (){      //...    },    m2 : function (){      //...    }  });

该方法的优点在于模块成员集中管理,缺点在于暴露模块内部状态,外部代码可直接修改私有成员。

3. 立即执行函数写法

为了保护模块私有成员,开发者采用立即执行函数(IIFE):

var module1 = (function(){    var _count = 0;    var m1 = function(){      //...    };    var m2 = function(){      //...    };    return {      m1 : m1,      m2 : m2    };  })();

该方法实现了模块私有成员的保护,但在模块较大或依赖关系复杂时,仍存在代码冗余和难以管理的问题。

4. 放大模式

针对大型模块或依赖继承需求,开发者采用放大模式

var module1 = (function (mod){    mod.m3 = function () {      //...    };    return mod;  })(module1);

该方法通过递归方式扩展模块功能,优于传统方式,但仍需处理模块加载顺序问题。

5. 宽放大模式

宽放大模式解决了模块加载顺序问题:

var module1 = ( function (mod){    //...    return mod;  })(window.module1 || {});

与传统放大模式相比,宽放大模式允许模块加载时使用空对象,简化了初始化逻辑。

6. 输入全局变量

为了提升模块独立性,开发者将全局变量显式输入模块:

var module1 = (function ($, YAHOO) {    //...  })(jQuery, YAHOO);

这种方式不仅保证了模块独立性,还使得依赖关系直观明了。

二、CommonJS、AMD和CMD的出现

CommonJS

CommonJS由Ryan Dahl在2009年创建,用于Node.js项目。其设计理念基于浏览器端模块化需求的不足,提出了一种同步加载的模块机制:

var math = require('math');math.add(2,3); // 5

AMD规范

AMD(Asynchronous Module Definition)采用依赖前置的方式定义模块:

require(['math'], function (math) {    math.add(2, 3);  });

其优势在于支持异步加载,避免了浏览器对长时间依赖加载的等待问题。目前主要的实现框架包括RequireJS和curl.js。

CMD规范

CMD(Common Module Definition)由国内开发者提出,采用就近依赖的方式定义模块:

define(function(require, exports, module) {  var $ = require('jquery.js');  var foo = require('foo');  var out = foo.bar();  $('div').addClass('active');  module.exports = out;});

其特点是懒加载,仅在模块使用时才加载依赖模块。

CommonJS、AMD和CMD的区别

  • 加载方式:CommonJS为同步加载,AMD和CMD为异步加载。
  • 依赖管理:AMD要求依赖前置,CMD支持就近依赖。
  • 加载机制:CMD实现懒加载,AMD采用预加载。
  • 三、ES6的使用

    ES6模块化

    ES6在语言标准层面实现了模块功能,简单而高效,已成为浏览器和服务器端通用的模块解决方案:

    const name = 'Byron';function printName(){    console.log(name);}function printFullName(firstName){    console.log(firstName + name);}const myModule = {    printName: printName,    printFullName: printFullName};export myModule;//加载模块import myModule, { printFullName } from './myModule.js';myModule.printName();printFullName('Michael');

    优势

  • 简洁性:采用exportimport简化了模块管理。
  • 可读性:模块结构清晰,便于维护和调试。
  • 四、最后再说说Browserify和Webpack

    Browserify/webpack

    Browserify和Webpack属于预编译模块化方案,相较于传统的在线解释器(如SeaJS/RequireJS),其优势在于:

  • 预编译:无需浏览器加载解释器,提升性能和加载效率。
  • 兼容性强:支持多种模块化风格(AMD/CMD/ES6),无需调整代码格式。
  • 工作原理

  • Browserify:将模块代码按需编译为浏览器可执行的代码。
  • Webpack:提供更高级的打包功能,支持模块分解和依赖优化。
  • 结语

    从最初的函数模块到CommonJS、AMD/CMD,再到ES6模块化,JavaScript模块化技术不断演进。通过选择合适的模块化方案(如ES6或Webpack),开发者能够在性能和开发体验之间找到最佳平衡,为项目打下坚实基础。

    转载地址:http://zqiuz.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现显示响应算法(附完整源码)
    查看>>
    Objective-C实现最小二乘多项式曲线拟合(附完整源码)
    查看>>
    Objective-C实现最快的归并排序算法(附完整源码)
    查看>>
    Objective-C实现最长公共子序列算法(附完整源码)
    查看>>
    Objective-C实现最长子数组算法(附完整源码)
    查看>>
    Objective-C实现最长字符串链(附完整源码)
    查看>>
    Objective-C实现有限状态自动机FSM(附完整源码)
    查看>>
    Objective-C实现极值距离算法(附完整源码)
    查看>>
    Objective-C实现根据cpu和磁盘序列号生成注册码( 附完整源码)
    查看>>
    Objective-C实现求众数(附完整源码)
    查看>>
    Objective-C实现牛顿下山法(附完整源码)
    查看>>
    Objective-C实现牛顿法算法(附完整源码)
    查看>>
    Objective-C实现状态模式(附完整源码)
    查看>>
    Objective-C实现生成正态分布数据(附完整源码)
    查看>>
    Objective-C实现电子词典(附完整源码)
    查看>>
    Objective-C实现离散傅里叶变换(附完整源码)
    查看>>
    Objective-C实现移位密码加解密(附完整源码)
    查看>>
    Objective-C实现给定一个数字数组,返回最大乘积数组中的 3 个数字算法(附完整源码)
    查看>>
    Objective-C实现维吉尼亚密码加解密算法(附完整源码)
    查看>>
    Objective-C实现维吉尼亚密码加解密算法(附完整源码)
    查看>>