关于模块化:爪哇学习笔记JavaScript模块化变迁史
1. 幼年期——无模块化按性能将js代码放到不同的JS文件,在模板中通过script标签按需援用 <script src="a.js"></script><script src="b.js"></script>文件拆散是模块化的第一步 存在的问题: 净化全局作用域 => 不利于大型项目的开发及多人团队的共建2. 成长期——命名空间模式繁多全局变量JavaScript中一个风行的命名空间模式是抉择一个全局变量作为次要的援用对象。比方jQuery库就是应用这种形式。var myApplication = (function () { function(){ //... }, return{ //... }})();命名空间前缀命名空间前缀模式其思路十分清晰,就是抉择一个独特的命名空间,而后在其前面申明申明变量、办法和对象。var myApplication_propertyA = {};var myApplication_propertyB = {};function myApplication_myMethod() {}对象字面量表示法对象字面量模式能够认为是蕴含一组键值对的对象,每一对键和值由冒号分隔,键也能够是代码新的命名空间。var myApplication = { // 能够很容易的为对象字面量定义性能 getInfo:function() { // *** }, // 能够进一步撑持对象命名空间 models:{}, views:{ pages:{} }, collections:{}};嵌套命名空间嵌套命名空间模式能够说是对象字面量模式的升级版,它也是一种无效的防止抵触模式,因为即便一个命名空间存在,它也不太可能领有同样的嵌套子对象。var myApplication = myApplication || {}; // 定义嵌套子对象 myApplication.routers = myApplication.routers || {}; myApplication.routers.test = myApplication.routers.test || {};IIFE(Immediately Invoked Function Expression,立刻调用函数表达式)IIFE实际上就是立刻执行匿名函数。在JavaScript中,因为变量和函数都是在这样一个只能在外部进行拜访的上下文中被显式地定义,函数调用提供了一种实现公有变量和办法的便捷形式。IIFE是用于封装利用程序逻辑的罕用办法,以爱护它免受全局名称空间的影响,其在命名空间方面也能够施展其非凡的作用。var namespace = namespace || {};(function( o ){ o.foo = "foo"; o.bar = function(){ return "bar"; };})(namespace);console.log(namespace);// 定义一个简略的模块const iifeModule = (() => { let count = 0; return { increase: () => ++count, reset: () => { count = 0; } }})();iifeModule.increase();iifeModule.reset();// 依赖其余模块的IIFEconst iifeModule = ((dependencyModule1, dependencyModule2) => { let count = 0; return { increase: () => ++count, reset: () => { count = 0; } }})(dependencyModule1, dependencyModule2);iifeModule.increase();iifeModule.reset();// Revealing Module(揭示模块)模式const iifeModule = (() => { let count = 0; function increaseCount() { ++count; } function resetCount() { count = 0; } return { increase: increaseCount, reset: resetCount }})();iifeModule.increase();iifeModule.reset();/** * 揭示模块模式定义: * 在模块模式的根底上,在返回的公有范畴内,从新定义所有的函数和变量。并返回一个匿名的对象。他领有所有指向公有函数的指针。 * Module模式最后被定义为一种在传统软件工程中为类提供公有和共有封装的办法。JS这里最后应用IIEF封装 **/命名空间注入命名空间注入是IIFE的另一个变体,从函数包装器外部为一个特定的命名空间“注入”办法和属性,应用this作为命名空间代理。这种模式的长处是能够将性能行为利用到多个对象或命名空间。var myApplication = myApplication || {};myApplication.utils = {};(function () { var value = 5; this.getValue = function () { return value; } // 定义新的子命名空间 this.tools = {};}).apply(myApplication.utils);(function () { this.diagnose = function () { return "diagnose"; }}).apply(myApplication.utils.tools);命名空间注入是用于为多个模块或命名空间指定一个相似的性能根本集,但最好是在申明公有变量或者办法时再应用它,其余时候应用嵌套命名空间曾经足以满足需要了。主动嵌套的命名空间function extend(ns, nsStr) { var parts = nsStr.split("."), parent = ns, pl; pl = parts.length; for (var i = 0; i < pl; i++) { // 属性如果不存在,则创立它 if (typeof parent[parts[i]] === "undefined") { parent[prats[i]] = {}; } parent = parent[parts[i]]; } return parent;}// 用法var myApplication = myApplication || {};var mod = extend(myApplication, "module.module2");3. 成熟期CJS——CommonJS每个文件就是一个模块,有本人的作用域。在一个文件外面定义的变量、函数、类,都是公有的,对其余文件不可见。如果想在多个文件分享变量,必须定义为global对象的属性。CommonJS标准规定,每个模块外部,module变量代表以后模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。require办法用于加载模块。为了不便,Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部,有一行这样的命令。 ...