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,存储在一个根据名字来管理的模块列表中。

以上内容,纯属个人理解,如果有不对之处,还请大家热心指正。

原文地址:https://www.cnblogs.com/developer-ios/p/10772846.html

时间: 2024-09-28 22:23:56

requirejs中的define的相关文章

关于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, doAnoth

ThinkPHP 3.2.2中使用define(&#39;BUILD_CONTROLLER_LIST&#39;,&#39;Index,User,Menu&#39;)无法生成相应控制器

笔者最近在学习ThinkPHP框架,按照官方开发手册,在架构一节中,按照手册,绑定Admin模块却无法生成相应的文件. <?define('BIND_MODULE','Admin'); // 绑定Admin模块,如果没有则生成该模块define('BUILD_CONTROLLER_LIST','Index,User,Menu');//生成InderxContoller,UserController,MenuControllerdefine('BUILD_MODEL_LIST','User,Men

浅谈c/c++头文件中#ifndef/#define/#endif的用法

想必很多人都看过“头文件中用到的 #ifndef/#define/#endif 来防止该头文件被重复引用”.但是是否能理解“被重复引用”是什么意思?头文件被重复引用了,会产生什么后果?是不是所有的头文件中都要加入#ifndef/#define/#endif 这些代码? 1. 其实“被重复引用”是指一个头文件在同一个cpp文件中被include了多次,这种错误常常是由于include嵌套造成的.如:存在a.h文件#include "c.h"而此时b.cpp文件导入了#include &q

requirejs中 shim

使用requireJS的shim参数,完成jquery插件的加载 时间 2014-10-31 13:59:10  CSDN博客 原文  http://blog.csdn.net/aitangyong/article/details/40653335 主题 jQueryRequireJS 没有requireJS框架之前,如果我们想使用jquery框架,会在HTML页面中通过<script>标签加载,这个时候jquery框架生成全局变量$和jQuery等全局变量.如果项目中引用了requireJS

requireJS中使用setTimeout和setInterval遇到的问题和解决方式

javascript中与定时相关的API有setTimeout()和setInterval(),这2个函数功能不同,但是使用方式是一样的. javascript中下面的写法,相当于是定义了一个密闭空间,在其中定义的变量和函数都是私有,只能本模块内访问. (function(){ var msg = "msg"; })(); //报错 alert(msg); 以前我写javascript,都是使用setTimeout("say('aty');",1000);这种方式,

oracle中SET DEFINE意思

et define off关闭替代变量功能 在SQL*Plus中默认的"&"表示替代变量,也就是说,只要在命令中出现该符 号,SQL*Plus就会要你输入替代值.这就意味着你无法将一个含有该符号的字符串输入数据库或赋给变量,如字符串“SQL&Plus”系统会 理解为以“SQL”打头的字符串,它会提示你输入替代变量 Plus的值,如果你输入ABC,则最终字符串转化为“SQLABC”. set define off 则关闭该功能,“&”将作为普通字符,如上例,最终字

requirejs 中的坑

题记:使用requirejs三个月,记录requirejs遇到的各种问题 1.当css插件遇到iframe弹窗 config配置 'WdatePicker':{ //ie8下使用define依赖此模块时,不能成功下载此css deps: ['jquery'/*,'css!/commonjs/plugins/My97DatePicker/skin/WdatePicker.css'*/] }, 使用define不能正确下载到css模块,ie8下会报下载超时的错误 使用require获取此模块则可以正

PHP 中 const define 的区别

在php中定义常量时,可用到const与define这两种方法,那他们到底有什么区别呢? 1.const用于类成员变量的定义,一经定义,不可修改.define不可用于类成员变量的定义,可用于全局常量. 2.const可在类中使用,define不能. 3.const不能在条件语句中定义常量. 4.const只能接受静态的标量,而define可采用任何的表达式. 5.const定义的常量时大小写敏感的,而define可通过第三个参数(为true表示大小写不敏感)来指定大小写是否敏感. 6.const

VS中设置#define _CRT_SECURE_NO_WARNINGS的两种方式

1.我们在编译老的用C语言的开源项目如lua源包的时候,可能因为一些老的.c文件使用了strcpy,scanf等不安全的函数,而报警告和错误,而导致无法编译通过. 2.此时我们有两种解决方案: a.在指定的源文件的开头定义:#define _CRT_SECURE_NO_WARNINGS  (只会在该文件里起作用) b.在项目属性里设置,这会在整个项目里生效,依次选择:属性->配置属性->C/C++ ->预处理器->预处理器定义->编辑 最下面加上一行:_CRT_SECURE_