本文实例讲述了JS前端模块化原理与实现方法。分享给大家供大家参考,具体如下:
1.什么是前端模块化
模块化开发,一个模块就是一个实现特定功能的文件,有了模块我们就可以更方便地使用别人的代码,要用什么功能就加载什么模块。
2.模块化开发的好处
1)避免变量污染,命名冲突
2)提高代码利用率
3)提高维护性
4)依赖关系的管理
3.前端模块化的进程
前端模块化规范从原始野蛮阶段现在慢慢进入“文艺复兴”时代,实现的过程如下:
3.1 函数封装
我们在讲到函数逻辑的时候提到过,函数一个功能是实现特定逻辑的一组语句打包。在一个文件里面编写几个相关函数就是最开始的模块了
function m1() { // ... } function m2(){ //... }
这样做的缺点很明显,污染了全局变量,并且不能保证和其他模块起冲突,模块成员看起来似乎没啥关系。
3.2 对象
为了解决这个问题,有了新方法,将所有模块成员封装在一个对象中
var module = new Object({ _count:0, m1:function (){ ```}, m2:function (){ ```} })
这样,两个函数就被包在这个对象中,看起来没有什么问题,当我们要使用的时候,就是调用这个对象的属性方法
module.m1()
那么问题来了,这样写法会暴露全部的成员,内部状态可以被外部改变,比如外部的代码可直接改变计数器的值
module._count = 10
3.3 立即执行函数(IIFE)
var module = (function(){ var _count = 5; var m1 = function (){ ```}; var m2 = function (){ ```}; return{ m1:m1, m2:m2 } })()
以上就是模块化开发的基础中的基础,以后会说其他更深层次的模块化开发。
接下来了解几种模块化规范。
1)commonJS
commonJS由nodeJS发扬光大,这标志着js模块化正式登场。
一. 定义模块
根据commonJS规范,一个单独的文件是一个模块,每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非为global对象的属性。
二. 模块输出
模块只有一个出口,module.exports对象,我们需要把模块希望输出的内容放入该对象。
三. 加载模块
加载模块用require方法,该文件读取一个文件并且执行,返回文件内部的module.exports对象。
var name = 'Byron'; function printName(){ console.log(name); } function printFullName(firstName){ console.log(firstName + name); } module.exports = { printName: printName, printFullName: printFullName }
然后加载模块
var nameModule = require('./myModel.js'); nameModule.printName();
2)AMD
Asynchronous Moudule Definition,中文名是一步模块。它是一个在浏览器端模块化开发的规范,由于不是js原生支持,使用AMD规范进行页面开发需要用到对应的函数库,也就是大名鼎鼎的Require.js,实际上AMD是RequireJS在推广过程中对模块化定义的规范化的产出。
RequireJS主要解决两个问题:
1)多个js文件可能有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器。
2)js加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应的时间越长。
//定义模块 define(['dependency'],function(){ var name = 'Byron'; function printName(){ console.log(name); } return { printName:printName } }) //加载模块 require(['myModule'],function(my){ my.printName(); })
语法:
requireJS定义了一个函数define,它是全局变量,用来定义模块。
define(id,dependencies,factory)
- ——id 可选参数,用来定义模块的标识,如果没有提供该参数,脚本文件名(去掉拓展名)
- ——dependencies 是一个当前模块用来的模块名称数组
- ——factory 工厂方法,模块初始化要执行的函数或对象,如果为函数,它应该只被执行一次,如果是对象,此对象应该为模块的输出值。
在页面上使用require函数加载模块;
require([dependencies], function(){});
require()函数接受两个参数:
- ——第一个参数是一个数组,表示所依赖的模块;
- ——第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块
AMD推崇的是依赖前置,被提前罗列出来并会背提前下载并执行,后来做了改进,可以不用罗列依赖模块,允许在回调函数中就近使用require引入并下载执行模块。
3)CMD
即common module definition
就像AMD有个requireJS,CMD有个浏览器实现的sea.js,sj要解决的问题和rj一样,只不过在模块定义方式和模块加载时机上有所不同。
cmd是sea.js在推广过程中的规范化产出,sea.js是另一种前端模块化工具,它的出现缓解了requireJS的几个痛点。
efine(id, deps, factory)
因为CMD推崇一个文件一个模块,所以经常就用文件名作为模块id;
CMD推崇依赖就近,所以一般不在define的参数中写依赖,而是在factory中写。
factory有三个参数:
function(require, exports, module){}
一,require
require 是 factory 函数的第一个参数,require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口;
二,exports
exports 是一个对象,用来向外提供模块接口;
三,module
module 是一个对象,上面存储了与当前模块相关联的一些属性和方法。
demo
// 定义模块 myModule.js define(function(require, exports, module) { var $ = require('jquery.js') $('div').addClass('active'); }); // 加载模块 seajs.use(['myModule.js'], function(my){ });
AMD与CMD区别
总结如下:
最明显的区别就是在模块定义时对依赖的处理不同。
AMD推崇依赖前置 在定义模块的时候就有声明其依赖的模块
CMD推崇就近依赖 只有在用到某模块的时候再去require
AMD和CMD最大的区别是对依赖模块的执行时机处理不同,注意不是加载的时机或者方式不同。
很多人说requireJS是异步加载模块,SeaJS是同步加载模块,这么理解实际上是不准确的,其实加载模块都是异步的,只不过AMD依赖前置,js可以方便知道依赖模块是谁,立即加载,而CMD就近依赖,需要使用把模块变为字符串解析一遍才知道依赖了那些模块,这也是很多人诟病CMD的一点,牺牲性能来带来开发的便利性,实际上解析模块用的时间短到可以忽略。
为什么我们说两个的区别是依赖模块执行时机不同,为什么很多人认为ADM是异步的,CMD是同步的(除了名字的原因。。。)
同样都是异步加载模块,AMD在加载模块完成后就会执行改模块,所有模块都加载执行完后会进入require的回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行。
CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的。
这也是很多人说AMD用户体验好,因为没有延迟,依赖模块提前执行了,CMD性能好,因为只有用户需要的时候才执行的原因。
感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]