一、模块化的由来1、最早我们这样写代码,所有的方法都写在一起,容易命名冲突,污染global全局函数foo(){}函数栏(){}2.简单的封装(Namespace方式)减少了全局变量的数量,但是仍然可以通过myFunc.foo来操作数据,unsafevarmyFunc={_private:'nosafe',foo:function(){console.log(this._private)}}myFunc._private=5;myFunc.foo();3.匿名闭包(IIFE模式)函数是javascript中唯一的localScope,无法操作里面的数据varmodule=(function(){var_private='safenow';varfoo=function(){console.log(_private);}返回{foo:foo}})();or(function(){var_private='safenow';varfoo=function(){console.log(_private);}//暴露模块window.module={foo:foo}})()module._private;//未定义的module.foo();我们的功能需要依赖模块来完成,这时候就需要往里面注入模块//这是模块模式的基础varmodule=(function($){var_private=$('body');varfoo=function(){console.log(_private);}//公开模块return{foo:foo}//导入模块})(JQuery);或(函数(全局){var_private='安全';varfoo=function(){console.log(_private);}//公开模块global.module={foo:foo}//导入模块})(window)module.foo();二、模块化规范1、commonjs暴露模块:默认exports为{},第一个相当于覆盖exports,第二个相当于给exports添加属性module.exports=值;exports.xxx=值;importmodule:importthird-partymodule:require(packagename)importcustommodule:require(modulefilepath)implementation:serverside:node环境直接使用浏览器端:使用browserify打包工具,否则浏览器无法识别browserifysrc/app.js-obundle.js代码演示://module1.jsmodule.exports={msg:'module1',foo:function(){console.log(this.msg);}};//module2.jsmodule.exports=function(){console.log('module2');};//module3.jsexports.foo=function(){console.log('foomodule3');};exports.bar=function(){console.log('barmodule3');};exports.arr=[1,224,2,4,2,4784,3];//app.jsconstuniq=require('uniq')constmodule1=require('./module1');constmodule2=require('./module2');constmodule3=require('./module3');module1.foo();module2();module3.foo();module3.bar();console.log(uniq(module3.arr));3.Commonjs详解一、模块加载策略Node.js模块分为两大类:native(核心)模块:native模块在Node.js源码编译时编译成二进制执行文件,加载速度是最快的。文件模块:文件模块是动态加载的,加载速度比原生模块慢。Tips:Node.js既缓存了原生模块,也缓存了文件模块,所以第二次require时不会有重复的开销。其中,nativemodules定义在lib目录下,filemodules不定。2.require文件搜索策略要点:从文件模块缓存中加载原生模块的优先级仅次于文件模块缓存的优先级。native模块也有缓存区,也是优先从缓存区加载。require方法接受以下参数传递:http、fs、路径等,原生模块。(node自带的模块)/mod或../mod,相对路径的文件模块。/pathtomodule/mod,文件模块的绝对路径。mod,一个不是本机模块的文件模块。(npmpackage)模块路径的生成规则是//从当前文件目录开始找到node_modules目录//然后依次进入父目录,找到父目录下的node_modules目录//依次迭代直到根目录下的node_modules目录['/home/jackson/research/node_modules','/home/jackson/node_modules','/home/node_modules','/node_modules']//另外还有全局模块路径,是相对于当前节点执行文件目录(../../lib/node)。//如果环境变量中设置了HOME目录和NODE_PATH目录,则整个路径还包括NODE_PATH和HOME目录下的.node_libraries和.node_modules[NODE_PATH,HOME/.node_modules,HOME/.node_libraries,execPath/../../lib/node]3.包结构package.json文件应该存在于包的顶级目录中。二进制文件应包含在bin目录中。JavaScript代码应包含在lib目录中。文档应该在doc目录中。单元测试应该在测试目录中。当Node.js没有找到目标文件时,它会尝试将当前目录作为包加载,所以package.json文件中最重要的字段是main。对于require,只需要main属性。但除此之外,包需要接受安装、卸载、依赖管理、版本管理等过程,所以CommonJS为package.json文件定义了如下必要的字段名:包名需要在NPM上是唯一的。不能包含空格。description:包的描述。通常它会出现在一些列表中。版本:版本号。语义版本号(http://semver.org/),通常为x.y.z。这个版本号很重要,经常用在一些版本控制的场合。keywords:一组关键字。用于NPM中的类别搜索。维护者:包维护者数组。数组元素是一个JSON对象,包含三个属性:name、email和web。contributors:一组包贡献者。第一个是包的作者本人。在开源社区中,如果提交的patch被合并到master分支,则需要添加贡献patch的人。该格式包含姓名和电子邮件。"contributors":[{"name":"JacksonTian","email":"mail@gmail.com"},{"name":"fengmk2","email":"mail2@gmail.com"}],bugs:可以提交错误的URL。它可以是电子邮件地址(mailto:mailxx@domain)或网页地址(http://url)。%E3%80%82)licenses:包使用的许可证。示例:"licenses":[{"type":"GPLv2","url":"http://www.example.com/licenses/gpl.html",}]repositories:托管源代码的地址数组。dependencies:当前包所需的依赖项。这个属性非常重要。NPM将使用此属性来帮助您自动加载依赖包。其他请参考链接:深入Node.js模块机制详解JavaScript模块化开发前端模块化详解(完整版)
