如今javascript的流行,前端的代码愈来愈复杂,因此咱们须要软件工程的思想来开发前端。模块化是必不可少的,这样不只可以提升代码的可维护性、可扩展性以及鲁棒性,更大的好处就是可以提高整个团队的开发效率,也可以让新进的程序员更快的接手工做。今天晚上根据前辈们的经验,写啦一个简单的模块定义的封装组件,当是练手吧。不过感受仍是蛮好用的。javascript
其实忽然就学习模块化的javascript开发,那仍是比较丈二和尚,摸不着头脑的。不过若是是作事后台开发的程序员们,可能对于模块化的开发思想并不陌生,由于后台的这方面技术已经很熟悉了。那么这里我就分享一下前端javascript模块化开发的学习。前端
若是有软件工程背景,那么这一思想就是你自身就应该掌握的。模块(module)就是能够组合、分解以及更换的单元,其实也知足组合大于继承等这些带来的好处吧。若是当作一个系统的话,咱们能够从软件体系结构来理解,模块是较大系统中的独立部件,功能、状态与接口反映外部特性,逻辑反映的是内部特性。java
模块化的开发模式为前端带来了新大陆,这点不得不认可,如今前端的愈加成熟,须要软件工程的这种思想。
玉伯也发表过前端模块化开发的价值git
3.了解目前技术,哪些和模块化开发沾边程序员
1) 开发功能模块的时候,能够采用Eva的解决方案(YUI3 + Minify)。github
2) 使用流行的javascript模块加载框架:seajs。数组
3) 若是喜欢轻巧的东西,也能够尝试带刀的easy.js,不错的一个模块加载框架。数据结构
4) 也能够尝试支付宝的Alice,这是一款基于CMD规范的东东,首页却是挺小清新的。app
5) 现在比较火的NodeJS这是必需要了解和学习的。框架
好啦,了解完上面那些技术后,模块化的前端模式应该很熟悉了,若是想扎实一下的话还能够了解一下AMD、CMD规范,具体是什么东西,google一下。接下来咱们就来构造一个简单的模块定义器吧,其实写的时候还挺简单的,不过主要是吸取思想,这样学习技术才不会跟不上时代。
module: { //模块名称 moduleName: moduleName, //模块依赖集合 dependencies: dependencies, //模块实例工厂 factory: factory }
因此咱们最后可以造成模块定义的代码以下:
define: function ( moduleName, dependencies, factory ) { if( !modules[moduleName] ) { //模块信息 var module = { moduleName: moduleName, dependencies: dependencies, factory: factory }; modules[moduleName] = module; } return modules[moduleName]; }
这样咱们就定义好了模块,那么咱们的入口在哪里呢?咱们还须要定义一个use的方法,来成为所谓的main,这样绑定好了才可以调用,如今想来程序也都是这样的。下面这段代码经过递归的产生模块依赖的全部实例,可是这里浪费了一部分instances数组的空间,有时间能够再作哈优化。
use: function ( moduleName ) { //使用括号的方式访问属性,实现动态的赋值(详情查阅“.”和[]的区别) var module = modules[moduleName]; //产生单个实例 if( !module.instance ) { var instances = [], len = module.dependencies.length - 1; for( var i = 0; i <= len; i++ ) { var dependency = module.dependencies[i], instance = dependency.instance; if( instance ) { instances.push( instance ); } else { //递归,将每次产生的实例放入数组 instances.push( arguments.callee( dependency ) ); } } //生成实例 module.instance = module.factory.apply( null, instances ); } return module.instance; }
最后我造成完整的本身的小库。
(function ( window, undefined ) { var modules = {}; var Sky = { //定义模块的基本信息 //1.模块名称,2.模块的依赖,3.产生实例的工厂 define: function ( moduleName, dependencies, factory ) { if( !modules[moduleName] ) { //模块信息 var module = { moduleName: moduleName, dependencies: dependencies, factory: factory }; modules[moduleName] = module; } return modules[moduleName]; }, //使用依赖 use: function ( moduleName ) { var module = modules[moduleName]; //产生单个实例 if( !module.instance ) { var instances = [], len = module.dependencies.length - 1; for( var i = 0; i <= len; i++ ) { var dependency = module.dependencies[i], instance = dependency.instance; if( instance ) { instances.push( instance ); } else { //递归,将每次产生的实例放入数组 instances.push( arguments.callee( dependency ) ); } } //生成实例 module.instance = module.factory.apply( null, instances ); } return module.instance; } }; window.Sky = Sky || {}; })(window);
下面咱们来一个完整的例子来使用一下以上咱们构建的轻巧代码。
Sky.define("constant.PI", [], function() { return 3.1415926; }); Sky.define("shape.Circle", ["constant.PI"], function( pi ) { function Circle(r) { this.r = r || 0; }; Circle.prototype.area = function() { return pi * this.r * this.r; }; return Circle; }); Sky.define("shape.Rectangle", [], function() { function Rectangle(width, height) { this.width = width || 0; this.height = height || 0; }; Rectangle.prototype.area = function() { return this.width * this.height; }; return Rectangle; }); Sky.define("ShapeTypes", ["shape.Circle", "shape.Rectangle"], function( Circle, Rectangle ) { return { 'CIRCLE': Circle, 'RECTANGLE': Rectangle }; }); Sky.define("ShapeFactory", ["ShapeTypes"], function( ShapeTypes ) { return { getShape: function(type) { var shape; switch (type) { case 'CIRCLE': shape = new ShapeTypes[type](arguments[1]); break; case 'RECTANGLE': shape = new ShapeTypes[type](arguments[1], arguments[2]); break; } return shape; } }; }); var ShapeFactory = Sky.use("ShapeFactory"); console.log(ShapeFactory.getShape("CIRCLE").area()); console.log(ShapeFactory.getShape("RECTANGLE", 2, 3).area());
是否是感受js代码变得更加清爽了?嘿嘿,上面的例子也是面向接口的,你们也能够看看。
参考前辈:http://blog.jobbole.com/43649/
也许代码有出入,有些地方前辈写得不够细心的我补上了一些,嘿嘿,可是思路是参考这位前辈的。