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 };可以用对象声明,不会影响结果。
导出单独的方法用exports: exports.get=function(){console.log('获取数据')} 导出一个对象用module.exports module.exports = obj; |
仿写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));