计算机基础——更适合程序员的编程必备基础知识|完结无密
下载看水印
最早的时候,通过文件划分的形式实现模块化,将功能状态数据各自单独放到不同的 JS 文件中。 每个文件作为独立模块,引入到页面,一个script标签对应一个模块,然后调用模块化的成员。
js复制代码<script src="module1.js"></script> <script src="module2.js"></script>
弊端:模块与模块之间没有依赖关系,维护困难,无私有空间。项目变大时,上述问题更明显。
解决:命名空间
命名空间
每个模块暴露全局对象,模块的内容挂载到对象中。
js复制代码window.moduleA = { method1: function() { console.log('moduleA#method1') } }
弊端:这种方式未解决模块与模块之间没有依赖关系的问题。
立即执行函数
使用立即执行函数为模块提供私有空间,通过参数的形式作为依赖声明。
js复制代码// module-a.js (function ($) { var name = 'module-a' function method1 () { console.log(name + '#method1') $('body').animate({ margin: '200px' }) } window.moduleA = { method1: method1 } })(jQuery)
评价:上述方式用script标签在页面引入模块,模块加载不受代码控制。时间一久维护起来麻烦。
解决:页面用引入一个JS入口文件,其余用到的模块通过代码控制。按需加载。以及制定模块化的规范。如今流行的模块规范有ES Modules,以及在ES6之前CommonJS、AMD浏览器和服务器通用的模块解决方案。
二、CommonJS、AMD、ES Modules
CommonJS
主要用于服务器端开发(如 Node.js)。CommonJS规范通过 module.exports 导出模块,通过 require 函数加载模块。CommonJS 模块是同步加载的,它是为了解决 JavaScript 的作用域问题而定义的模块形式,可以使每个模块它自身的命名空间中执行。
CommonJS模块规范主要分为引用、定义、标识模块三部分:
js复制代码module.exports = function( value ){ return value * 2; } /** * 模块引用 * * 使用require()方法来引入一个模块; * 这里引入 模块:moduleA,并复制给变量multiplyBy2; * */ var multiplyBy2 = require('./moduleA'); var result = multiplyBy2(4); /** * 模块标识 * * 指传给require()的参数 可以是小驼峰命名的模块名或是路径 * * require("模块名"):当前目录下的node_modules目录中的模块 * require("路径"):指定目录的指定模块 * */ /** * 模块定义 * * module对象:module对象指的模块自身 * export属性:module对象的属性,为外部提供接口 * */ module.exports = function( value ){ return value * 2; }
特点:
CommonJS是同步加载模块,模块加载的顺序,按照其在代码中出现的顺序。
所有代码都运行在模块作用域,不会污染全局作用域。
模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
注意:浏览器不兼容CommonJS的根本原因,在于缺少四个Node.js环境的变量。module、exports、require、global。所以只要能够提供这四个变量,浏览器就能加载 CommonJS 模块。
领取专属 10元无门槛券
私享最新 技术干货