模块浅析
程序员文章站
2022-07-12 12:09:13
...
/**
*模块浅析
*/
function aa(){
var name = 'Saber';
var age = 20;
function info(){
console.log(name);
}
function another(){
console.log(age);
}
return {
info:info,
another:another
}
}
var bb = aa();
bb.info();//Saber
bb.another();//20
/**
*这里来看一下上面的代码,
* 我们通过调用aa()函数来创建一个模块实例,如果不执行外部函数aa(),内部作用域和闭包都无法被创建
* aa()函数返回了一个对象,这个对象里有内部函数,却没有内部数据变量的引用,这里的内部变量保持了隐藏且私有的状态,
* 这里的这个对象可以看做模块的公共API
*/
/**
*说到这里,那么模块模式需要具备的两个必要条件是:
* 1、必须有外部函数,并且至少被调用一次(每次调用都会创建一个新的模块实例)
* 2、封闭函数必须至少返回一个内部函数,这样内部函数才能在私有作用域中形成闭包,然后对内部变量进行访问或者修改
*/
/**
* 上面的aa()函数可以被调用任意次数来创建新的模块实例,如果只需要一个实例的话,可以把这个aa函数改一下,变成一个单例模式
*/
var ss = (function(){
var name = 'Dark';
var age = 12;
function info(){
console.log(name);
}
function another(){
console.log(age);
}
return {
info:info,
another:another
}
})();
ss.info();//Dark
ss.another();//12
/**
*我们将模块函数改成了一个IIFE函数,立即执行这个函数之后将返回的对象直接赋给了ss变量,
* 当然,只要是函数就能够接收参数,这是没跑的了
*/
var dd = (function(str){
var name = 'Dark';
var age = 12;
function info(){
console.log(name);
}
function another(){
console.log(age);
}
function special(){
console.log(str);
}
return {
info:info,
another:another,
special:special
}
})('传进一个参数!!!!');
dd.special();//传进一个参数!!!!
/**
*如果我们定义一个对象,这个对象返回的是公共的API,就像下面这样
*/
function ff(){
var str = '我就是一个普通的变量';
function ww(){
console.log(str);
}
function ee(){
str = '普通变量被ee()函数改变了!!!!!'
}
var obj = {
ww:ww,
ee:ee
}
return obj;//这里和上面的唯一区别就是弄了一个对象,然后返回这个对象,并不是直接返回一个对象了
}
var hh = ff();
hh.ww();//我就是一个普通的变量
hh.ee();
hh.ww();//普通变量被ee()函数改变了!!!!!
/**
*我在书里看到这儿的时候,说是这样方便从内部对模块实例进行修改,但是从我自己来看的话,和直接返回没有啥区别啊,
* 这点我不太懂,如果有人看到这里,方便给解答一下就太好了!!!!
*/
/**
*现代模块机制
*/
var rr = (function vv(){
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);//核心代码 :把impl返回的值赋值给了modules[name]上
}
function get(name){
return modules[name];
}
return {
define:define,
get:get
}
})();
rr.define('bar1',[],function(){
function hello(who){
return 'say hello to ' + who;
}
return {
hello:hello
}
});//这个函数是将hello这个函数,放在了modules对象里,key叫做bar1
rr.define('foo',['bar1'],function(foo){
/**
* 第二个参数为bar1,作用是,在define函数里,for循环把modules里的bar1的值,赋给了bar1(deps[i]),
* 然后将bar1的值当做参数传进了impl中,所以这里的foo是能够接收到参数的,
* bar1的值为hello这个函数
*/
var hungry = 'hippo';
function awesome(){
console.log(bar.hello(hungry).toUpperCase())//SAY HELLO TO HIPPO
}
return {
awesome:awesome
}
});//把awesome这个函数放进了modules里,key叫做foo
var bar = rr.get('bar1');
var foo = rr.get('foo');
console.log(bar.hello('hippo'));//say hello to hippo
foo.awesome();
/**
*哇!上面这个代码好难懂啊,我整了半天才读懂他们,
* 但是我发现一件事,就是模块再怎么变,宗旨不会变
* 就是要有内部函数返回
* rr这个模块管理器的作用就是,接收函数,并把他们保存在一个根据名字来管理的模块列表中,就是modules里,进行存取
*/
/**
*未来的模块机制
*/
/**
*bar.js
*/
function hello(who){
return 'say hello to ' + who;
}
export {hello};
/**
*foo.js
*/
import {hello} from './bar';//导入了hello这个模块
var hungry = 'hippo';
function awesome(){
console.log(hello(hungry).toUpperCase());
}
export {awesome};
/**
*baz.js
*/
import {hello} from './foo';
import {awesome} from './bar';
console.log(hello('saber'));
awesome();
/**
* 这里用的是es6里的import和export,
* 说到这里,有几点需要注意的我说一下:
* 文件里可以有好多 export ,但是只能有一个 export default
* export 可以直接导出,类似:export let name1 = 'XXX',函数也可以直接导出,也可以有一个导出列表
* 类似:export { name1, name2};
* 但是用export导出的,导入的时候需要加上 { },类似:import {hello} from './foo';
* 但是export default,导入的时候不需要加,export default 用法和 export 一样的
* 可以直接导出变量函数,也可以弄一个导出列表
*/
/**
*es6中为模块增加了一级语法支持,将文件作为独立的模块来处理,
* 每个模块可以引入其他模块或API成员,可以导出自己的API
* 函数的模块不是能够稳定识别的模式,他们在运行时才会被考虑进来
* 而es6的模块更加稳定,在编译时就可以检查模块的引用是否真实存在,并且报错
* es6把独立文件作为模块进行引用,浏览器或引擎有一个模块加载起,可以导入模块时异步的加载模块文件
*/
上一篇: 廖雪峰_使用模块 if __name__ == '__main__' 解释(转载)
下一篇: 模块