目前JS模块化有四种规范,common.js运行在node环境。浏览器环境运行三种规范,ES6、requireJs(Amd)和 Seajs(Cmd)
在Node环境中模块都是同步执行,这和其他服务器语言一样。其他规范在浏览器环境中都是异步调用模块。node环境引用模块为require、导出模块为export或者module.export。
(export实际上是给module.export对象加数据。例如:
exports.name = 'likang xie'; exports.age = 21; console.log(module.exports); //{ name: 'likang xie', age: 21 }
requireJs和Seajs都是用define来定义模块,不同点在于requirejs对于依赖模版先加载,seajs只对于用到的模块加载。而且seajs比requrejs执行顺序更科学。当然seajs需要对加载的模块进行解析(用正则对代码进行解析,提取出依赖)。导致seajs运行更慢。
1.requireJS的两种常用的写法
1.1常规模式
function A(x,y){ this.a = x; this.b =y ; //给这个构造函数添加成员,很多情况是extend给函数添加成员, //而extend赋值最多的是这个函数添加事件处理。 } var m = A.prototype; m.getA=function(){} //A实例都具有getA … var h = new A(); return h;
下面稍稍有点不一样,但是本质是一样的。
function A(){ extend(this,{ ..... }); //好处是A函数可以copy其他模块一些特征。 } u = A.prototype; s.mixin(u); //u可以获取s模块中的方法,mixin为借用。 return a = new A //a有s模块和copy模块中的所有属性和方法
1.2另外一种模式,模块中有私有成员变量
define(“xx”,[],function(){ function e(e) { //提供对外的构造函数接口。 this.id = e.toUpperCase() } var t, i = window.localStorage; e.init = function(e) { //初始化对私有变量赋值。 if (!t) t = "BDBG_IM_" + e + "_" } e.prototype.key = function() { //e的对象能访问的原型对象。 return t + this.id } return e; }); a.init(b), var w = new a("chat”);
2.require-ensure和require
区别在于require中模块不执行也会下载,而require-ensure中的模块是必须执行才能下载,他们的调用有点不同:
require.ensure(["modules/tips.jsx"], function(require) { var a = require("modules/tips.jsx"); // ... }, 'tips'); //tips对应于webpack中chunkFileName的名字
3.requirejs写插件
//调用形式,exports对象添加三个插件,每一个插件都代表一个对象,该对象包含几个方法。 exports.plugin(require("./message/text")); exports.plugin(require("./message/file")); exports.plugin(require("./plugin/text")); //函数定义,给w这个静态私有变量赋值。w为对象。 exports.plugin = function(e) { if (e.encoder) w.addEncoder(e.encoder); if (e.decoder) //e.decoder是一个对象,有e.decoder.img、e.decoder.text.... w.addDecoder(e.decoder); if (e.pick) b.on("pick", e.pick) } //w是一个模块对象,该对象定义如下: var e = {}, t = {}, exports = {}; //两个特权函数,对静态私有变量e和t赋值, return exports.addEncoder = function(t) { //本质是复制。把插件中的对象收集起来 Object.keys(t).forEach(function(i) { e[i] = t[i] } ) } , exports.addDecoder = function(e) { Object.keys(e).forEach(function(i) { t[i] = e[i] } ) }
调用插件给收集方法的模块添加插件的方法,后面调用插件中的方法,就可以直接引用收集方法的模块。
var c ={}; var u ={}; var exports = {}; c = { c1:function(){ } }; u = { u1:function(){}, u2:function(){}, .... } function deal(p1){ var t = u(p1); return function(t,x,y){ u[p1] //调用u中定义的方法 } } Object.keys(c).forEach(function(p){ exports(p) = deal(p); }); return exports