JavaScript深入系列之闭包
archerU opened this issue · comments
闭包
函数在定义时的词法作用域以外的地方被调用,并且函数可以继续访问定义时的词法作用域。
模块
模块模式必要条件:
1.必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块实例)。
2.封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态。
function CoolModule() {
var something = "cool";
var another = [1,2,3];
function doSomething() {
console.log(something);
}
function doAnother() {
console.log(another.join(" ! "));
}
return {
doSomething: doSomething,
doAnother: doAnother
};
}
var foo = CoolModule();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3
这个模式在JavaScript中被称为模块。最常见的实现模块模式的方法通常被称为模块暴露,这里展示的是其变体。
AMD的模块机制(requirejs)
大多数模块依赖加载器/管理器本质上都是将这种模块定义封装进一个友好的API。
var myModules = (function Manager(){
var modules = [];
function define(name,deps,impl) {
for(var i=0; i<deps.length; i++) {
deps[i] = modules[deps[i]];
}
modules[name] = impl.apply(impl,deps);
}
function get(name) {
return modules[name];
}
return {
define: define,
get: get
};
})();
这段代码的核心是 modules[name] = impl.apply(impl,deps)
为了模块的定义引入了包装函数(可以传入任何依赖),并且将返回值,也就是模块的API,储存在一个根据名字来管理的模块列表中。
使用以上函数来定义模块
MyModules.define("bar",[],function(){
function hello(who) {
return "Let me introduce:" + who;
}
return {
hello: hello
};
});
MyModules.define("foo",["bar"],function(){
var hungry = "hippo";
function awesome() {
console.log(bar.hello(hungry).toUpperCase());
}
return {
awesome: awesome
};
});
var bar = MyModules.get("bar");
var foo = MyModules.get("foo");
console.log(
bar.hello("hippo");
); // Let me introduce: hippo
foo.awesome(); // LET ME INTRODUCE: HIPPO
CMD 的模块机制(seajs)
CMD 依赖就近,延迟执行。
// CMD
define(function(require, exports, module) {
var a = require('./a');
a.doSomething();
var b = require('./b');
b.doSomething();
})
UMD 的模块机制
异步加载,异步执行,兼容服务器、浏览器端
CommonJS 的模块机制
- 一个单独的文件就是一个模块
- 加载模块采用同步方式,加载完成后才能执行后面的操作
- 加载模块使用require方法,该方法读取一个文件并执行,最后返回内部的exports对象
ES6的模块机制
ES6将文件当作独立的模块处理。
bar.js
function hello(who) {
return "Let me introduce:" + who;
}
export hello;
foo.js
// 仅从"bar"模块导入hello()
import hello from "bar";
var hungry = "hippo";
function awesome() {
console.log(
hello(hungry).toUpperCase()
);
}
export awesome;
baz.js
module foo from "foo";
module bar from "bar";
console.log(
bar.hello("rhino");
); // Let me introduce: rhino
foo.awesome(); // LET ME INTRODUCE: HIPPO
模块文件中的内容会被当作好像包含在作用域闭包中一样来处理,就和前面介绍的函数闭包模块一样。