CommonJS规范的主要内容:
模块必须通过 module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。
CommonJS模块的特点:
(1)所有代码运行在当前模块作用域中,不会污染全局作用域
(2)模块同步加载,根据代码中出现的顺序依次加载
(3)模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
一个简单的例子:
demo.js
module.exports.name = \'Aphasia\';module.exports.getAge = function(age){
console.log(age)
};//需要引入demo.js的其他文件var person = require(\'./demo.js\')
module对象
根据CommonJS规范,每一个文件就是一个模块,在每个模块中,都会有一个module对象,这个对象就指向当前的模块。module对象具有以下属性:
(1)id:当前模块的bi
(2)exports:表示当前模块暴露给外部的值
(3)parent: 是一个对象,表示调用当前模块的模块
(4)children:是一个对象,表示当前模块调用的模块
(5)filename:模块的绝对路径
(6)paths:从当前文件目录开始查找node_modules目录;然后依次进入父目录,查找父目录下的node_modules目录;依次迭代,直到根目录下的node_modules目录
(7)loaded:一个布尔值,表示当前模块是否已经被完全加载
示例:
module.js
module.exports = {
name: \'Aphasia\',
getAge: function(age){
console.log(age)
}
}console.log(module)
执行 node module.js
1、module.exports
从上面的例子我们也能看到,module对象具有一个exports属性,该属性就是用来对外暴露变量、方法或整个模块的。当其他的文件require进来该模块的时候,实际上就是读取了该模块module对象的exports属性。
简单的使用示例
module.exports = \'Aphasia\';module.exports.name = \'Aphasia\';module.exports = function(){
//dosomething
}module.exports = {
name: \'Aphasia\',
getAge: function(){
//dosomething
}
}
2、exports对象
一开始我很郁闷,既然module.exports就能满足所有的需求,为什么还有个exports对象呢?其实,二者之间有下面的关系
(1)首先,exports和module.exports都是引用类型的变量,而且这两个对象指向同一块内存地址。在node中,二者一开始都是指向一个空对象的
exports = module.exports = {};
可以在REPL环境中直接运行下面代码 module.exports ,结果会输出一个 {}
(2)其次, exports对象是通过形参的方式传入的,直接赋值形参会改变形参的引用,但是并不能改变作用域外的值。 这句话是什么意思呢?我们举个例子。
var module = {
exports: {}
}
var exports = module.exports
function change(exports) {
//为形参添加属性,是会同步到外部的module.exports对象的
exports.name = "Aphasia"
//在这里修改了exports的引用,并不会影响到module.exports
exports = {
age: 24
}
console.log(exports) //{ age: 24 }
}
change(exports)
console.log(module.exports) //{exports: {name: "Aphasia"}}