Created
December 27, 2013 06:55
-
-
Save ufologist/8143562 to your computer and use it in GitHub Desktop.
理解RequireJS中的模块
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * 理解RequireJS中的模块 | |
| * ================================ | |
| * 重点在于介绍RequireJS模块定义/运作/使用的基本原理, 不考虑依赖管理即其他方面的问题. | |
| * 看看define和require到底做了些什么. | |
| * | |
| * @author Sun | |
| * @version 2013-12-27 | |
| */ | |
| // 1. RequireJS的内部结构 | |
| // -------------------------------- | |
| // 我们把RequireJS精简到最小(属个人理解, 可能与真实实现有差别), 只要能定义模块/使用模块即可 | |
| var RequireJS = { | |
| mod: {}, // 模块映射(相当于Map) | |
| define: function(name, object) { // 定义(注册)模块 | |
| // 如果注册的模块是方法则执行一次, 相当于我们常见的IIFE | |
| this.mod[name] = typeof object == 'function' ? object() : object; | |
| }, | |
| require: function(name) { // 获取模块 | |
| return this.mod[name]; | |
| } | |
| }; | |
| // 2. RequireJS是如何完成定义模块的 | |
| // -------------------------------- | |
| // 请先回顾下JavaScript Module Pattern | |
| // | |
| // define相当于定义(注册)模块, 模块的代码立即被执行且只执行一次 | |
| // | |
| // 如下用于定义模块的js你假设他们是通过浏览器一个个顺序加载并执行的. | |
| // 因此相当于将他们合并到一个js文件中就类似下面的效果了. | |
| // | |
| // mod1.js | |
| // 注册一个构造函数模块 | |
| RequireJS.define('mod1', function() { // 模块闭包 | |
| var privateVar1 = 'SpongeBob Squarepants mod1'; | |
| function A() { | |
| this.instanceProperty = 'I am READY! mod1'; | |
| } | |
| A.prototype.setPrivate = function(value) { | |
| // 形成闭包, 引用外部变量(私有变量) | |
| privateVar1 = value; | |
| }; | |
| A.prototype.getPrivate = function() { | |
| return privateVar1; | |
| }; | |
| return A; | |
| }); | |
| // mod2.js | |
| // 注册另外一个构造函数模块, 但代码与mod1.js基本保持一样(Σ( ° △ °)会不会冲突啊?) | |
| RequireJS.define('mod2', function() { | |
| var privateVar1 = 'SpongeBob Squarepants mod2'; | |
| function A() { | |
| this.instanceProperty = 'I am READY! mod2'; | |
| } | |
| A.prototype.setPrivate = function(value) { | |
| privateVar1 = value; | |
| }; | |
| A.prototype.getPrivate = function() { | |
| return privateVar1; | |
| }; | |
| return A; | |
| }); | |
| // mod3.js | |
| // 注册单例 | |
| RequireJS.define('mod3', { | |
| singletonVar: 'singletonVar', | |
| singletonFn: function() { | |
| return 'singletonFn: ' + this.singletonVar; | |
| } | |
| }); | |
| // 其他单例示例 | |
| RequireJS.define('mod4', 'singleton'); | |
| RequireJS.define('mod5', 3.14); | |
| RequireJS.define('mod6', [ | |
| 2, 0, 1, 3, 12, 27 | |
| ]); | |
| // 3. RequireJS是如何使用模块的 | |
| // -------------------------------- | |
| // require仅仅只是从模块映射中按名字获取已经注册好的模块, 并不会执行模块代码! | |
| // | |
| // main.js | |
| var Mod1 = RequireJS.require('mod1'), | |
| Mod2 = RequireJS.require('mod2'), | |
| mod3 = RequireJS.require('mod3'), | |
| mod4 = RequireJS.require('mod4'), | |
| mod5 = RequireJS.require('mod5'), | |
| mod6 = RequireJS.require('mod6'); | |
| console.warn('-----获取到的模块-----'); | |
| console.log(Mod1); | |
| console.log(Mod2); | |
| console.log(mod3); | |
| console.log(mod4); | |
| console.log(mod5); | |
| console.log(mod6); | |
| console.warn('-----使用模块-----'); | |
| var m1 = new Mod1(), | |
| m2 = new Mod2(); | |
| console.log(m1.getPrivate()); | |
| console.log(m2.getPrivate()); | |
| console.warn('-----修改模块闭包中的私有变量-----'); | |
| m1.setPrivate('!!! new SpongeBob Squarepants mod1'); | |
| m2.setPrivate('!!! new SpongeBob Squarepants mod2'); | |
| console.log(m1.getPrivate()); | |
| console.log(m2.getPrivate()); | |
| console.warn('-----重新获取模块-----'); | |
| var Mod1a = RequireJS.require('mod1'), | |
| Mod2a = RequireJS.require('mod2'); | |
| var m1a = new Mod1a(); | |
| m2a = new Mod2a(); | |
| // 由于模块的代码只会执行一次, 模块闭包与模块本身是一对一的关系 | |
| // 重新获取(require)模块并不能起到刷新模块, 重新初始化模块的作用 | |
| console.log('m1', m1.getPrivate()); | |
| console.log('m2', m2.getPrivate()); | |
| console.log('m1a', m1a.getPrivate()); | |
| console.log('m2a', m2a.getPrivate()); | |
| console.warn('-----试试单例-----'); | |
| console.log(mod3.singletonVar); | |
| console.log(mod3.singletonFn()); | |
| console.warn('-----修改下单例的属性-----'); | |
| mod3.singletonVar = '!!! new singletonVar'; | |
| console.log(mod3.singletonVar); | |
| console.warn('-----重新获取模块-----'); | |
| var mod3a = RequireJS.require('mod3'); | |
| console.log(mod3a.singletonFn()); | |
| // 以下是执行结果 | |
| // -------------------------------- | |
| // | |
| // -----获取到的模块----- | |
| // function A() { | |
| // this.instanceProperty = 'I am READY! mod1'; | |
| // } | |
| // function A() { | |
| // this.instanceProperty = 'I am READY! mod2'; | |
| // } | |
| // Object {singletonVar: "singletonVar", singletonFn: function} | |
| // singleton | |
| // 3.14 | |
| // [2, 0, 1, 3, 12, 27] | |
| // | |
| // -----使用模块----- | |
| // SpongeBob Squarepants mod1 | |
| // SpongeBob Squarepants mod2 | |
| // | |
| // -----修改模块闭包中的私有变量----- | |
| // !!! new SpongeBob Squarepants mod1 | |
| // !!! new SpongeBob Squarepants mod2 | |
| // | |
| // -----重新获取模块----- | |
| // m1 !!! new SpongeBob Squarepants mod1 | |
| // m2 !!! new SpongeBob Squarepants mod2 | |
| // m1a !!! new SpongeBob Squarepants mod1 | |
| // m2a !!! new SpongeBob Squarepants mod2 | |
| // | |
| // -----试试单例----- | |
| // singletonVar | |
| // singletonFn: singletonVar | |
| // | |
| // -----修改下单例的属性----- | |
| // !!! new singletonVar | |
| // | |
| // -----重新获取模块----- | |
| // singletonFn: !!! new singletonVar | |
| // PS: 其他模块加载器的运作方式以此类推... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment