使用 Node.js 编写应用程序主要就是在使用:
- EcmaScript 语言
- 核心模块
- 第三方模块(必须通过 npm 来下载才可以使用)
- 自己写的模块
CommonJS 模块规范
在 Node 中的 JavaScript 还有一个很重要的概念:模块系统
- 模块作用域
- 使用 require 方法用来加载模块
- 使用 exports 接口对象用来导出模块中的成员
1.加载 require
语法: var 自定义变量名称 = require('模块')
两个作用:
- 执行被加载模块中的代码
- 得到被加载模块中的
exports
导出接口对象
2.导出 exports
- Node中是模块作用域,默认文件中所有成员都只在当前文件模块有效
对于希望可以被其他模块访问的成员,我们需要把这些公开的成员都挂载到exports
接口对象中就可以了。
导出多个成员(必须在对象中):
exports.a = 123
exports.b = 'hello'
exports.c = function () {
console.log('ccc')
}
exports.d = {
foo: 'bar'
}
导出单个成员:
module.exports = 'hello'
以下情况会覆盖:
module.exports = 'hello'
module.exports = function (x, y) {
return x + y
}
也可以这样来导出多个成员:
module.exports = {
add: function () {
return x + y
}
str: 'hello'
}
原理解析
-
在 node 中,每个模块内部都有一个自己的 module 对象,该 module 对象中,有一个成员叫:exports也是一个对象。如果你需要对外导出成员,只需要把导出的成员挂载到 module.exports 中。
我们发现,每次导出接口成员的时候都通过 module.exports.xxx = xxx的方式很麻烦,所以 Node 为了简化你的操作,专门提供了一个变量:exports 等于 module.exports。也就是说在模块中还有这么一句代码:
var exports = module.exports
-
当一个模块需要导出单个成员的时候,直接给 exports 赋值是不管用的,给 exports 赋值会断开和 module.exports 之间的引用,同理,给 module.exports 重新赋值也会断开。但是有一种引用方式比较特殊:
exports = module.exports
这个是用来重新建立引用关系的。 -
最终 return 的是 module.exports,不是 exports。默认在代码的最后有一句:
return module.exports
。谁来 require,谁就得到 module.exports
原理解析demo:
exports.foo = 'bar'
// ==> {foo: bar}
module.exports.a = 123
// ==> {foo: bar, a: 123}
// 重新赋值后:exports !== module.exports
// 最终 return 的是 module.exports,所以无论你 exports 中的成员是什么都没用
exports = {
a: 456
}
module.exports.foo = 'haha'
// ==> {foo: 'haha', a: 123}
// 没关系,混淆你的
exports.c = 456
// 重新建立了和 module.exports 之间的引用关系了
exports = module.exports
// 由于在上面建立了引用关系,所以这里是生效的
exports.a = 789
// ==> {foo: 'haha', a: 789}
// 前面再牛逼,在这里都全部推翻了,重新赋值
// 最终得到的是 Function
module.exports = function () {
console.log('hello')
}
网友评论