关于requirejs中的define的原理理解
我们已经了解到模块模式是为单例创建私有变量和特权方法的。
一个最基本的例子:
var foo=(function(){
var something='cool',
var another=[1,2,3];
function dosomething(){
console.log(something);
}
function doAnother(){
console.log(another.join('!'));
}
return {
doSomething:doSomething,
doAnother:doAnother
}
})();
foo.doSomething(); //cool
foo.doAnother(); //1!2!3
我们将模块函数转换成了立即执行函数,立即调用这个函数并将返回值直接赋值给单例的模块实例标识符。在函数内部定义了私有变量,并通过函数留下了接口,除了通过接口访问其内部的私有变量的值,在函数外部是无法访问它的值的,这也就保证了不会引起命名冲突,修改数据等问题,同时,模块还可以复用,大大提高了开发效率。
其实,大多数的模块倚赖加载器/管理器本质上都是将这种模块定义封装进一个友好的API(接口)。我们知道,在requirejs中,使用define([],function(){})来定一个模块的,来看下面一段原理性代码。
var MyModules=(function Manager(){
var moudules={}; //对象字面量
function define(name,deps,impl){
for(var i=0;i<deps.length;i++){
deps[i]=moudules[deps[i]];
}
moudules[name]=impl.apply(impl,deps);
console.log(moudules[name]);
}
function get(name){
return moudules[name];
}
return {
define:define,
get:get
};
})();
这里我们定义了一个匿名函数,并让他立即执行,然后将返回值传给了MyModules。
接下来我们执行这样一段代码:
MyModules.define('bar',[],function(){
function hello(who){
return 'Let me introduce:'+who;
}
return {
hello:hello
}
});
var bar=MyModules.get('bar');
console.log(bar.hello('nihao'));
看一下执行结果:
大致分析一下执行过程:
通过MyModules的公共接口define,同时,传给define的第二个参数是一个空数组,所以说,for循环会跳过,这时,最关键的一句是
impl.apply(impl,deps)
它会将impl也就是第三个匿名函数参数的this值绑定到函数自身的作用域并同时将第二个参数deps作为函数的参数传进去。
这时,modules对象中就多了一个bar属性,其大致的结构跟我们开篇讲的第一个例子,并没有什么两样,我们看一下,其结构:

也就相当于这样:
var bar=function(){
function hello(who){
return 'Let me introduce':+who;
}
return {
hello:hello
}
};
这时,我们再调用get函数获取到其属性,然后调用其hello()方法,结果也就一目了然了。
但这里,我们第二个参数是一个空数组,在requirejs中,也就相当于不倚赖任何模块,那当他需要依赖其他模块时,会是什么样的情况呢,他又是如何完成其他模块的加载的呢?
我们在代码的基础上,继续增加如下代码:
MyModules.define('foo',['bar'],function(bar){
var hungry='hippo';
function awesome(){
console.log(bar.hello(hungry).toUpperCase());
}
return {
awesome:awesome
}
});
var foo=MyModules.get('foo');
foo.awesome();
看一下其执行结果:
是按照我们预想的那样输出的。
我们再来分析一下执行过程:
其关键的步骤就是第二个参数是有一个数组值的数组,代码将执行遍历此数组操作,然后,将该数组的第一个值赋值为此前module对象中的bar属性对象,所以说该数组中的值也就也就指向了moudule对象中的bar属性对象(注意引用类型的复制问题)。
其也就当做参数传递到了modules对象的另外一个属性foo之中,其实,这也就完成了requirejs中加载模块的功能。这时,当我们引用bar模块中的公共接口的时候,其结果也就在情理之中了。
其实,这段代码的核心就是modules[name]=impl.apply(impl,deps)。为了模块的定义引入了包装函数(可以传入任何依赖),并将其返回值,也就是模块的API,存储在一个根据名字来管理的模块列表中。
以上内容,纯属个人理解,如果有不对之处,还请大家热心指正。
关于requirejs中的define的原理理解的更多相关文章
- requirejs中的define
关于requirejs中的define的原理理解 我们已经了解到模块模式是为单例创建私有变量和特权方法的.一个最基本的例子: var foo=(function(){ var something= ...
- 通过源码理解Spring中@Scheduled的实现原理并且实现调度任务动态装载
前提 最近的新项目和数据同步相关,有定时调度的需求.之前一直有使用过Quartz.XXL-Job.Easy Scheduler等调度框架,后来越发觉得这些框架太重量级了,于是想到了Spring内置的S ...
- RequireJS中的require如何返回模块
requirejs中定义AMD模块规则如下: define(function(){ var ProductManager={ Create:function(){ console.log(" ...
- C#中对IDisposable接口的理解
http://blog.sina.com.cn/s/blog_8abeac5b01019u19.html C#中对IDisposable接口的理解 本人最近接触一个项目,在这个项目里面看到很多类实现了 ...
- Linux VFS中write系统调用实现原理【转】
转自:http://blog.chinaunix.net/uid-28362602-id-3425881.html 目录 用户空间的write函数在内核里面的服务例程为sys_write Vfs_wr ...
- [BS-18] 对OC中不可变类的理解
对OC中不可变类的理解 OC中存在很多不可变的类(如NSString,NSAttributedString,NSArray,NSDictionary,NSSet等),用它们创建的对象存在于堆内存中,但 ...
- 对于requirejs AMD模块加载的理解
个人人为使用模块化加载的优点有三: 1,以我的项目为例:90%为图表展示,使用的是echarts,此文件较大,requirejs可以在同一个版本号(urlArgs)之下缓存文件,那么我就可以在访问登陆 ...
- RequireJS中的require返回模块
requirejs中定义AMD模块规则如下: define(function(){ var ProductManager={ Create:function(){ console.log(" ...
- 关于MySQL中的自联结的通俗理解
关于MySQL中的自联结的通俗理解 前言:最近在通过SQL必知必会这本书学习MySQL的基本使用,在学习中也或多或少遇到了点问题,我也正好分享给大家,我的这篇博客用到的所有表格的代码都是来自SQL必知 ...
随机推荐
- C语言递归回溯法迷宫求解
本例将随机产生一个10*10的迷宫输出后,在下面输出此迷宫的解法. 解法为从坐标(1,1)处进入,从(8,8,)出去,优先线路为先右后下再上最后为左. 不少人求解此题时运用的栈的相关知识,本例寻找线路 ...
- xtrabackup在线备份及还原
xtrabackup下载https://www.percona.com/downloads/XtraBackup/LATEST/xtrabackup文档https://www.percona.com/ ...
- WHAT?【 $.fn.extend() 】vs【 $.extend() 】
废话不多说,干货来了,转自http://www.cnblogs.com/hellman/p/4349777.html (function($){ $.fn.extend({ test:function ...
- vim实用技巧总结
1. 单个文件内实用mark来帮助跳转以及一些宏操作.(注意:mark不能用于多文件之间的跳转)mch 设置宏,保存到ch标记(不是ch寄存器)'ch 跳转到标记的行首`ch 跳转到标记的字符处另:为 ...
- codevs3027线段覆盖2(DP)题解
题目描述 Description 数轴上有n条线段,线段的两端都是整数坐标,坐标范围在0~1000000,每条线段有一个价值,请从n条线段中挑出若干条线段,使得这些线段两两不覆盖(端点可以重合)且线段 ...
- eclipse 一些快捷键
快捷键 alt + 上下方向键 向后缩进 shift + tab 整体向左移动 tab 就是向右移动 ctrl + Q 就是构建有参的构造方法 ctrl + E 是get set 方法,要把quick ...
- Webservice WCF WebApi
注明:改编加组合 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在.net平台下,你有很多的选择来构建一个HTTP Service ...
- Zabbix 中文使用手册
一.Zabbix简介 详情参考"企业监控利器-zabbix"http://waringid.blog.51cto.com/65148/904201. 二.Zabbix使用 2.1 ...
- 自定义dialog自动弹出软键盘
1.解决无法弹出输入法: 在show()方法调用之前,用dialog.setView(new EditText(context))添加一个空的EditText,由于是自定义的AlertDialog,有 ...
- USACO 3.3 TEXT Eulerian Tour中的Cows on Parade一点理解
Cows on Parade Farmer John has two types of cows: black Angus and white Jerseys. While marching 19 o ...