javascript之模块(闭包后传)

模块:

最常见的实现模块模式的方法通常被称为模块暴露;而这就可能用到闭包。

模块条件:

1.必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块 实例)。
2.封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并 且可以访问或者修改私有的状态。
【1.用于创建模块实例的函数(实现内部作用域和闭包);2.返回包含有内部函数(实现了对内部变量的隐藏和引用)的对象【可以看作模块的公共API】/或者直接返回内部函数; 】
show code to you!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var foo = (function Cool Module(id) {
function change() {
// 修改公共 API
public API.identify = identify2;
}
function identify1() {
console.log( id );
}
function identify2() {
console.log( id.to Upper Case() );
}
var public API = {
change: change,
identify: identify1
};
return public API;
})( "foo module" );
foo.identify(); // foo module
foo.change();
foo.identify(); // FOO MODULE

现代的模块机制

大多数模块依赖加载器/管理器本质上都是将这种模块定义封装进一个友好的API 。
show code to you again!!!

定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 ,储存在一个根据名字来管 理的模块列表(返回的对象)中。

### 使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
My Modules.define( "bar", [], function() {
function hello(who) {
return "Let me introduce: " + who;
}
return {
hello: hello
};
} );
My Modules.define( "foo", ["bar"], function(bar) {
var hungry = "hippo";
function awesome() {
console.log( bar.hello( hungry ).to Upper Case() );
}
return {
awesome: awesome
};
} );
var bar = My Modules.get( "bar" );
var foo = My Modules.get( "foo" );
console.log(
bar.hello( "hippo" )
); // Let me introduce: hippo
foo.awesome(); // LET ME INTRODUCE: HIPPO

未来的模块机制:

ES6中为模块增加了一级语法支持。但通过模块系统进行加载时,ES6会将文件当作独立的模块来处理。每个模块都可以导入其他模块或特定的 API 成员,同样也可以导出自己的 API成员。

【以下是难以理解的部分】
基于函数的模块并不是一个能被稳定识别的模式(编译器无法识别),它们的API语义只有在运行时才会被考虑进来。因此可以在运行时修改一个模块的API。相比之下,ES6模块 API更加稳定(API不会在运行时改变)。由于编辑器知道这一点,因此可以在(的确也这样做了)编译期检查对导入模块API成员的引用是否真实存在。
ES6 的模块没有“行内”格式,必须被定义在独立的文件中(一个文件一个模块)。

import 可以将一个模块中的一个或多个 API 导入到当前作用域中,并分别绑定在一个变量 上(在我们的例子里是 hello)。
module 会将整个模块的 API 导入并绑定到一个变量上(在 我们的例子里是 foo 和 bar)。
export 会将当前模块的一个标识符(变量、函数)导出为公共API 。这些操作可以在模块定义中根据需要使用任意多次。

star Huang wechat
my wechat public welcomes to your attention