CMD规范学习笔记——基于SEAJS实现
CMD(Common Module Definition):该规范明确了模块的书写格式和基本交互规则。通常一个模块就是一个JS文件。
通过define关键字来定义模块,最基本的格式为:
define(factory);//这里的define是一个全局函数,factory可以是函数或者合法的值。 |
一、factory为对象:
define({'foo':'foo'});//factory为对象,表示该模块的接口为对象。 |
例子:
html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>CMD规范的Define函数</title> <script type="text/javascript" src="../../sea-modules/seajs/seajs/2.2.0/sea.js"></script> <script type="text/javascript"> seajs.use("../../static/cmd/main");//使用模块 </script> </head> <body> </body> </html> |
定义模块1:cmdDefine.js
/** * define(factory) * 模块通过define关键字定义,它是一个全局的方法,factory可以是方法或者是对象和字符串等合法的值 */ //定义一个模块,该模块的对象接口为{'foo':"foo"} define({'foo':"foo"}); |
定义模块2:main.js
/** * 当factory为函数时,可以接受3个参数,function(require,exports,module) */ define(function(require) { //通过riquire引用模块 var cmdDefine=require('./cmdDefine'); alert(cmdDefine.foo);//输出对象foo }); |
结果:
二、factory为字符串
define("This is Test!"); |
结果:
三、factory为数字
define(100); |
结果:
四、当factory函数
cmdDefine.js
/** * define(factory) * 模块通过define关键字定义,它是一个全局的方法,factory可以是方法或者是对象和字符串等合法的值 */ //定义一个模块,该模块的对象接口为{'foo':"foo"} //define({'foo':"foo"});//对象 //define("This is Test!");//字符串 //define(100);//数字 //factory为函数 define(function(require,exports,module){ //构造函数 function CmdDefine(){ alert("This is CmdDefine Constructor!"); } //每个函数都有一个prototype原型对象,可以在原型对象上添加属性和方法,实例化对象的_proto_指向原型对象 CmdDefine.prototype.say=function(){ alert("This is CmdDefine say function!"); } module.exports=CmdDefine;//对外发布接口 }); |
main.js
/** * 当factory为函数时,可以接受3个参数,function(require,exports,module) */ define(function(require) { //通过riquire引用模块 var CmdDefine=require('./cmdDefine'); //alert(cmdDefine.foo);//输出对象foo //alert(cmdDefine);//输出字符串This is Test! var tmp = new CmdDefine();//创建CmdDefine实例 tmp.say();//调用say方法 }); |
结果:
五、define 也可以接受两个以上参数。字符串 id 表示模块标识,数组deps是模块依赖。带id和deps参数的define用法不属于 CMD 规范,而属于 Modules/Transport 规范。比如:
/** * define(factory) * 模块通过define关键字定义,它是一个全局的方法,factory可以是方法或者是对象和字符串等合法的值 */ //定义一个模块,该模块的对象接口为{'foo':"foo"} //define({'foo':"foo"});//对象 //define("This is Test!");//字符串 //define(100);//数字 //factory为函数 //define('cmdDefine',['jquery'],function(require,exports,module) //define接收3个参数,第一个为模块标识,第二个为依赖模块数组 define('cmdDefine',['jquery'],function(require,exports,module){ //构造函数 function CmdDefine(){ alert("This is CmdDefine Constructor!"); } //每个函数都有一个prototype原型对象,可以在原型对象上添加属性和方法,实例化对象的_proto_指向原型对象 CmdDefine.prototype.say=function(){ alert("This is CmdDefine say function!"); } module.exports=CmdDefine;//对外发布接口 }); |
在seajs中id和deps参数可以省略。省略时,可以通过构建工具自动生成。
六、判断当前页面是否有CMD模块加载器
define.cmd,一个空的对象可以用来判断当前页面是否存在CMD模块加载器。
if(tepyof define === "function" && define.cmd){ // 有 Sea.js 等 CMD 模块加载器存在 } |
七、require:是factory为函数时的第一个参数,也是一个函数,接受一个参数(模块标识ID),用于获取其他模块提供的接口。
/** * 当factory为函数时,可以接受3个参数,function(require,exports,module) */ define(function(require) { //通过riquire获取cmdDefine对外提供的接口 var CmdDefine=require('./cmdDefine'); //alert(cmdDefine.foo);//输出对象foo //alert(cmdDefine);//输出字符串This is Test! var tmp = new CmdDefine();//创建CmdDefine实例 tmp.say();//调用say方法 }); |
八、require.async:是一个方法,接受两个参数(id,callback) ,用于在模块内异步加载模块,并在模块加载完成之后调用回调函数,callback为可选。require是同步往下执行, require.async则是异步回调执行。 require.async 一般用来加载可延迟异步加载的模块。
实际测试中tmp为null,存在问题。
/** * 当factory为函数时,可以接受3个参数,function(require,exports,module) */ define(function(require) { //通过riquire引用模块 require.async('./cmdDefine',function(tmp){ alert("模块加载完成"); //tmp.say();//调用say方法 }); }); |
九、require.resolve:require.resolve(id)
使用模块系统内部的路径解析机制来解析并返回模块路径。该函数不会加载模块,只返回解析后的绝对路径。这可以用来获取模块路径,一般用在插件环境或需动态拼接模块路径的场景下。
/** * 当factory为函数时,可以接受3个参数,function(require,exports,module) */ define(function(require) { //通过riquire引用模块 var path=require.resolve('./cmdDefine'); alert(path); }); |
结果:
十、exports:Object,是一个对象,用于模块对外提供接口。exports 仅仅是 module.exports 的一个引用。在factory内部exports重新赋值时,并不会改变module.exports的值。因此给 exports赋值是无效的,不能用来更改模块接口。
第一种写法:通过exports添加属性或方法
define(function(require,exports,module){ exports.foo='foo'; exports.print=function(){ console.log('foo'); } }); |
第二种写法:直接通过return对外提供接口
define(function(require){ return { foo:'foo', print:function(){ console.log('foo'); } } }); |
第三种写法:如果return语句是模块的唯一代码,可以省略return
define({ foo : 'foo', print : function() { console.log('foo'); } }); |
第四种写法:通过module.exports对外提供接口
/** * define(factory) * 模块通过define关键字定义,它是一个全局的方法,factory可以是方法或者是对象和字符串等合法的值 */ define('cmdDefine',['jquery'],function(require,exports,module){ //构造函数 function CmdDefine(){ alert("This is CmdDefine Constructor!"); } //每个函数都有一个prototype原型对象,可以在原型对象上添加属性和方法,实例化对象的_proto_指向原型对象 CmdDefine.prototype.say=function(){ alert("This is CmdDefine say function!"); } module.exports=CmdDefine;//对外发布接口 }); |
直接给exports赋值是错误的。
/** * 不能通过给exports变量赋值对外提供接口, * exports只是module.exports的引用, * 直接赋值无法改变module.exports的值 * */ define(function(require) { exports = { foo : 'foo', print : function() { console.log('foo'); } } }); |
十一:module :Object,是一个对象,它储存与当前模块相关联的属性和方法。
1、module .id:String,模块唯一标识是一个字符串。define函数的第一个参数为模块ID。
/** * define(factory) * 模块通过define关键字定义,它是一个全局的方法,factory可以是方法或者是对象和字符串等合法的值 */ define('cmdDefine',['jquery'],function(require,exports,module){ //构造函数 function CmdDefine(){ alert("This is CmdDefine Constructor!"); } //每个函数都有一个prototype原型对象,可以在原型对象上添加属性和方法,实例化对象的_proto_指向原型对象 CmdDefine.prototype.say=function(){ alert("This is CmdDefine say function!"); } module.exports=CmdDefine;//对外发布接口 }); |
2、module.uri:String: 根据模块系统的路径解析规则得到的模块绝对路径。一般情况下(没有在define中手写id 参数时),module.id的值就是module.uri ,两者完全相同。
define(function(require,exports,module) { alert(`"id:"${module.id}`);//模块id alert(`"uri:"${module.uri}`); }); |
结果:
3、module.dependencies:Array:是一个数组,表示当前模块的依赖。
4、module.exports:Object :当前模块对外提供的接口。
传factory构造方法的exports参数是 module.exports 对象的一个引用。只通过 exports 参数来提供接口,有时无法满足开发者的所有需求。比如当模块的接口是某个类的实例时,需要通过 module.exports 来实现:
define(function(require, exports, module) { // exports 是 module.exports 的一个引用 console.log(module.exports === exports); // true // 重新给 module.exports 赋值 module.exports = new SomeClass(); // exports 不再等于 module.exports console.log(module.exports === exports); // false }); |
对 module.exports 的赋值需要同步执行,不能放在回调函数里。下面这样是不行的:
//x.js define(function(require, exports, module) { // 错误用法 setTimeout(function() { module.exports = { a: "hello" }; }, 0); }); |
在 y.js 里有调用到上面的 x.js:
//y.js define(function(require, exports, module) { var x = require('./x'); // 无法立刻得到模块 x 的属性 a console.log(x.a); // undefined }); |
CMD规范:https://github.com/cmdjs/specification/blob/master/draft/module.md
Common Module Definition / draft This specification addresses how modules should be written in order to be interoperable in browser-based environment. By implication, this specification defines the minimum features that a module system must provide in order to support interoperable modules. •Modules are singletons. •New free variables within the module scope should not be introduced. •Execution must be lazy. Module Definition A module is defined with define keyword, which is a function. define(factory); 1.The define function accepts a single argument, the module factory. 2.The factory may be a function or other valid values. 3.If factory is a function, the first three parameters of the function, if specified, must be "require", "exports", and "module", in that order. 4.If factory is not a function, then the module's exports are set to that object. Module Context In a module, there are three free variables: require , exports and module . define(function(require, exports, module) { // The module code goes here }); The require Function 1. require is a function i. require accepts a module identifier. ii. require returns the exported API of the foreign module. iii.If requested module cannot be returned, require should return null. 2. require.async is a function i. require.async accepts a list of module identifiers and a optional callback function. ii.The callback function receives module exports as function arguments, listed in the same order as the order in the first argument. iii.If requested module cannot be returned, the callback should receive null correspondingly. The exports Object In a module, there is a free variable called "exports", that is an object that the module may add its API to as it executes. The module Object 1. module.uri The full resolved uri to the module. 2. module.dependencies A list of module identifiers that required by the module. 3. module.exports The exported API of the module. It is the same as exports object. Module Identifier 1.A module identifier is and must be a literal string. 2.Module identifiers may not have a filename extensions like .js . 3.Module identifiers should be dash-joined string, such as foo-bar . 4.Module identifiers can be a relative path, like ./foo and ../bar . Sample Code A typical sample math.js define(function(require, exports, module) { exports.add = function() { var sum = 0, i = 0, args = arguments, l = args.length; while (i < l) { sum += args[i++]; } return sum; }; }); increment.js define(function(require, exports, module) { var add = require('math').add; exports.increment = function(val) { return add(val, 1); }; }); program.js define(function(require, exports, module) { var inc = require('increment').increment; var a = 1; inc(a); // 2 module.id == "program"; }); Wrapped modules with non-function factory object-data.js define({ foo: "bar" }); array-data.js define([ 'foo', 'bar' ]); string-data.js define('foo bar'); |
原文:https://github.com/seajs/seajs/issues/242
CMD规范学习笔记——基于SEAJS实现的更多相关文章
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- Linux学习笔记——基于鸟哥的Linux私房菜
Linux学习笔记--基于鸟哥的Linux私房菜 ***** ARM与嵌入式linux的入门建议 (1) 学习基本的裸机编程:ARM7或ARM9,理解硬件架构和控制原理 (这一步是绝对的根基) (2) ...
- AMD规范学习笔记
背景 NodeJS的一套比较简洁 Moudles 规范, 使得在服务器端的模块化变得更加简单.很长一段时间,很多公司或者项目都有自己的一套模块化机制, 却未能形成一套统一的标准, NodeJS的Mou ...
- WCF学习笔记(基于REST规则方式)
一.WCF的定义 WCF是.NET 3.0后开始引入的新技术,意为基于windows平台的通讯服务. 首先在学习WCF之前,我们也知道他其实是加强版的一个面向服务(SOA)的框架技术. 如果熟悉Web ...
- deep learning深度学习之学习笔记基于吴恩达coursera课程
feature study within neural network 在regression问题中,根据房子的size, #bedrooms原始特征可能演算出family size(可住家庭大小), ...
- PSR规范学习笔记
PSR已经经历了5次变革,如今PSR4就是最新的标准,但是还是有必要了解下5个版本的内容的,于是去php-fig网站看了下英文原版: 大概看了遍,发现这规范很多的必须很多时候只是建议,但是PHP解析器 ...
- Vue学习笔记-基于CDN引入方式简单前后端分离项目学习(Vue+Element+Axios)
一 使用环境 开发系统: windows 后端IDE: PyCharm 前端IDE: VSCode 数据库: msyql,navicat 编程语言: python3.7 (Windows x86- ...
- Linux常用命令学习笔记——基于CentOS 7
前言:最近在linux培训时复习了一下linux系统中一些常用的命令和用法,整理成了笔记,虽然些许零散,但希望对大家有所帮助. 目录 0.帮助指令 1.关机.重启.注销命令 2.文件和目录操作命令 3 ...
- GP card规范学习笔记
9. APDU命令参考 9.1 总的编码规则 A.生命周期状态的编码 可执行的装载文件 b8 b7 b6 b5 b4 b3 b2 b1 含义 16进制命令 0 0 0 0 0 0 0 1 LO ...
随机推荐
- 联想z470 win7 64位双系统继续恢复镜像法安装黑苹果10.9.3
之前的方法是安装 10.9 http://blog.csdn.net/kissing_huo/article/details/23559239的 苹果最新的swift的语言 出来 必须最新的xcod ...
- 【LeetCode-面试算法经典-Java实现】【064-Minimum Path Sum(最小路径和)】
[064-Minimum Path Sum(最小路径和)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a m x n grid filled with ...
- 84.Node.js -Mongoose 方法
转自:https://www.cnblogs.com/chris-oil/p/9136534.html Mongoose 参考手册 标签(空格分隔): MongoDB Mongoose 是什么? 一般 ...
- 3.bind与仿函数以及普通函数
#include <iostream> #include <string> #include <vector> #include <algorithm> ...
- 安卓开发--scrollview
package com.cnn.scrollviewdemo01; import android.R.integer; import android.annotation.SuppressLint; ...
- Failed to start metasploit.service: Unit metasploit.service not found的解释
不多说,直接上干货! root@kali:~# service metasploit start Failed to start metasploit.service: Unit metasploit ...
- sapui5 One or more constraints have not been satisfied.
Getting error in creating a new project for UI5 One or more constraints have not been satisfied. slo ...
- java 多线程——join()方法
在java语言中,join()方法的作用是让调用该方法的线程在执行完run()方法后,再执行join 方法后面的代码. 简单点说就是,将两个线程合并,用于实现同步的功能. 具体而言:可以通过线程A的j ...
- struts2中标签库访问静态成员
struts2中是可以访问静态成员的,需要以下设置: 1.设置配置文件 struts.xml 中如下: <!-- 设置运行通过ONGL访问静态方法 --> <constant nam ...
- bzoj 2287: 【POJ Challenge】消失之物 动态规划
Code: #include<cstdio> #include<algorithm> #include<queue> #include<cstring> ...