Skip to content

Instantly share code, notes, and snippets.

@ufologist
Created December 27, 2013 06:55
Show Gist options
  • Select an option

  • Save ufologist/8143562 to your computer and use it in GitHub Desktop.

Select an option

Save ufologist/8143562 to your computer and use it in GitHub Desktop.
理解RequireJS中的模块
/**
* 理解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