Node.js中每个模块都是一个独立构造函数,解释器会为每个.js文件添加如下代码:
(function(exports,require, module, __filename, __dirname){
//exports:本质是一个空对象{ } 用于声明向外部导出的自己的成员
//require:本质是一个函数fn 用于导入其它的模块,创建指定模块对象
//module:
//__filename:
//__dirname:
//自己编写的文件内容
})
//module_user.js //(function(export,require,module,__filename,__dirname){ var userCount = 998; var userLogin = function(){ console.log("User login..."); } var userLogout = function(){ console.log("User logout..."); } //向外公开自己内部的文件 exports.uCount = userCount; exports.uLogin = userLogin; exports.uLogout = userLogout; //})
//app.js var moduleUser = require("./module_user.js");//引入另外一个模块js后缀可以省略 /** * Node.js中每个模块都是一个module对象 * */ //使用module_user.js中的成员 console.log(moduleUser); console.log(moduleUser.uCount); console.log(moduleUser.uLogin); moduleUser.uLogout();//只能使用module_user.js自己exports的成员
每个模块都可以使用自己的require()函数引入另一个模块——底层本质就是创建了指定模块的一个对象实例。
require('./模块文件名')
每个模块可以使用exports对象向外导出/公开一些自己内部的成员供其它模块使用。
exports. 成员名 =成员值; Node.js的模块中exports和module.exports对象的区别是什么? 二者都可以用于向外界导出自己内部的成员。但: module变量指代当前模块对象,真正导出的是modue.exports; Node.js底层有代码: exports = module.exports。 所以:若只是给exports对象添加新的成员,则等价于给module.exports添加新成员; 但是若修改了exports的指向,则不会产生实质的作用,即exports指向了一个新的对象,不再与module.exports指向同一个对象,例如 exports = { size:getSize; };声明并不起作用。 但是module.exports = { sum:function(){}, avg:avg };可以用对象声明,不会影响结果。 |
仿写nodejs的URL模块:
/**_URLjs * 接收一个URL字符串,解析出各个部分 * @param path 要解析的URL字符串,形如: http://www.jd.com:80/ad/index.html?name=gemini&pwd=123 * @returns {{}包含解析出各个部分的对象} */ function parse(path){ var result = {}; var i1 = path.indexOf('://'); result.protocol = path.substring(0,i1); var i2 = path.lastIndexOf(':');//i2是:最后一次出现的下标位置 result.hostname = path.substring(i1+3,i2); var i3 = path.indexOf('/',i2);//最后一个:后面的第一个/的下标位置 path = path.substring(i3); result.path = path; var i4 = path.indexOf('?'); result.queryString = path.substring(i4+1); result.query = {}; var list = result.queryString.split('&');//['name=gemini','pwd=123'] for(var v of list){ var prop = v.split('=');//v[0]:['name','gemini'];v[1]:['pwd','123'] result.query[prop[0]] = prop[1]; } return result; } //向外部导出自己内部的成员 module.exports.parse = parse;
主程序模块app.js
const util = require('util');//加载node.js官方提供的原生模块,不需要加路径 const moduleUrl = require("./_URL");//const 避免修改模块的内容 var p ='http://www.jd.com:80/ad/index.html?name=gemini&pwd=123'; var obj = moduleUrl.parse(p); console.dir(obj); var str = util.inspect(obj); console.log(str);
1.自定义模块的两种形式
(1)文件模块
创建一个js文件,如m3.js,导出需要公开的数据。其它模块可以require('./m3')模块
(2)目录模块
方式1:必须使用index.js命名模块
创建一个目录,假设名为m4,其中创建名为index.js的文件,导出需要公开的数据。其它模块可以require('./m4')模块
方式2:必须在目录中新建package.json文件并在其中配置参数:"main": "./文件名.js"
创建一个目录,假设名为m5,其中创建package.json文件,其中声明main属性指定默认执行的启动JS文件,如5.js,其中导出需要公开的数据。其它模块可以require('./m5')模块
{ "name": "application-name", "version": "0.0.1", "main":"5.js" }
方式3:必须将目录放在node_modules根目录中并配置main参数
创建一个目录,必须名为node_modules,其中再创建目录模块,假设名为m6,其中创建package.json文件,其中声明main属性指定默认执行的启动JS文件,如6.js,其中导出需要公开的数据。其它模块可以require('m6')模块
练习:
1.创建自定义模块:
2. 配置package.json
{ "name": "rectangle", "version": "1.0", "main": "./index.js" }3. 在主程序中使用
app.js
const circle = require("circle"); console.log(circle.perimeter(3)); const rectangle = require("rectangle"); console.log("rectangle's size is "+rectangle.size(2,7));