JavaScript的模块系统详解(一)

由于JavaScript开发变得越来越普遍,命名空间和依赖管理更加难以处理,前赴后继的程序员们提出来很多的解决方案,本文将探讨一些经典的方案,并描述这些方案解决了哪些问题。

为什么需要模块系统

作为开发人员,我们一定知道封装和依赖。在实际的项目开发中,我们通常会引入项目依赖,如果没有封装机制,这可能会导致代码间的各种冲突,所以我们在看一些C语言的源码库的时候,经常会看到各种前缀:

#ifndef MYLIB_INIT_H
#define MYLIB_INIT_H

enum mylib_init_code {
    mylib_init_code_success,
    mylib_init_code_error
};
enum mylib_init_code mylib_init(void);
//(...)

#endif //MYLIB_INIT_H

封装可以有效解决代码冲突。但在Web端的js开发中,仅仅做到封装是不够的,我们还要确保各依赖模块能按照正确的顺序加载和执行。

我们通过Backbone.js的一个例子来说明手动控制依赖的加载顺序:

<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Backbone.js Todos</title>
        <link rel="stylesheet" href="todos.css"/>
    </head>

    <body>
        <script src="../../test/vendor/json2.js"></script>
        <script src="../../test/vendor/jquery.js"></script>
        <script src="../../test/vendor/underscore.js"></script>
        <script src="../../backbone.js"></script>
        <script src="../backbone.localStorage.js"></script>
        <script src="todos.js"></script>
    </body>

    <!-- (...) -->

</html>

随着现代JavaScript的开发越来越复杂,依赖管理也变得越来越困难,引入模块系统是大势所趋。

特殊的模块封装

在介绍现代模块系统之前,我们先介绍一种特殊的编程模式,在一定程度上它也可以解决很多JavaScript应用的模块管理。


var myRevealingModule = (function () {
    var privateVar = "Ben Cherry",
        publicVar = "Hey there!";

    function privateFunction() {
        console.log( "Name:" + privateVar );
    }

    function publicSetName( strName ) {
        privateVar = strName;
    }

    function publicGetName() {
        privateFunction();
    }

    // Reveal public pointers to
    // private functions and properties
    return {
        setName: publicSetName,
        greeting: publicVar,
        getName: publicGetName
    };
})();

myRevealingModule.setName( "Paul Kinlan" );

这是通过函数作用域来实现私有变量的封装,有函数return语句暴露对外访问的接口。在上面的例子中,函数内部不一定需要通过var来声明变量,函数也无需立即执行,命名函数也可以作为一个模块来使用。
在很长一段时间,这种方式可以很好地实现模块封装,但它不能解决依赖管理的问题,同时也无法引入其它模块,除非在函数内容通过eval执行外部JavaScript。

特点

  • 实现简单,原生支持;
  • 在单个文件中定义多个模块。

缺陷

  • 无法导入其他文件中的模块;
  • 手动处理依赖管理;
  • 无法实现依赖的异步加载;
  • 无法有效处理依赖间的循环引用;
  • 无法静态分析源码依赖。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章