1.在Node中编写应用程序主要就是在使用:
①ECMAScripta语言
和浏览器不一样,在Node中没有BOM、DOM
②核心模块
文件操作的fs
http服务的http
url路径操作模块
path路径处理模块
os操作系统信息
③第三方模块
art-template
必须通过npm来下载才可以使用
④自己写的模块
2.Node中采用的是commonJS模块规范
模块系统包括
模块作用域
使用require方法来加载模块
使用exports接口对象用来导出模块中的成员
exports是一个对象,我们可以通过为这个对象添加成员实现数据的导出
在foo.js中不用exports导出的话,在main.js是拿不到foo.js的数据的,这体现了文件作用域
如果一个模块需要导出某个成员,而非挂载,需要用module.exports
多次使用module.exports会覆盖
也可以用module.exports导出多个成员
3.exports和module.exports原理解析
如果要导出多个成员:exports.xxx = xxx 或者 module.exports = {}
如果要导出单个成员:module.exports = xxx
源码中是这样写的
var module = {
exports: {
...
}
...
}
...
var exports = module.exports
...
return module.exports
Node为了简化操作, 所以有var exports = module.exports这样一句
这里,exports是module.exports的引用
exports.xxx = xxx 和 module.exports.xxx = xxx是等价的
所以,当你用exports=xxx的时候,exports会指向新的一块内存,module.exports指向的就不是同一块内存区域了,那么你对exports的修改就不会反映到module.exports上
但我最后return的是module.exports,所以用exports=xxx不能导出单个成员
也就是说,给exports赋值会断开和module.exports之间的联系,同理,给module.exports重新赋值也会断开
下面看个例子
main.js
const fooExports = require('./foo')
console.log(fooExports)
foo.js
exports.foo = 'hello' // {foo='hello'}
module.exports.a = 'bar' // {foo='a', a='bar'}
exports = { // exports !== module.exports
a: 456
}
module.exports.foo = 'hhh' // {foo='hhh', a='bar'}
exports.c = 789 // 不影响
exports = module.exports // exports和module.exports重新建立关系
exports.a = 111 // {foo='hhh', a='111'}
4.模块标识路径和文件操作路径
require模块加载的路径中的相对路径不能省略 ./
fs.readFile中的文件加载路径可以省略 ./