nodeJS采用CommonJS规范实现了模块系统
CommonJS规范规定了如何定义一个模块,如何导出模块中的数据以及如何使用定义好的模块
2.1在CommonJS规范中,一个文件就是一个模块
2.2在CommonJS规范中,每个文件中的数据都是私有地,对其他文件不可见
2.3在CommonJS规范中,每个文件中的数据,必须通过exports导出之后,其他文件才可以使用
2.4在CommonJS规范中,要想使用其他文件暴露的数据,必须通过require导入模块后才可以使用
有三中导出数据的方式,但无论使用哪种方式导出,使用时都必须先用require导入
3.1 exports.xxx = xxx
//a.js
let name = 'andy';
function sum(a,b){
console.log(a + b);
}
exports.str = name;
exports.fn = sum;
//exports是一个对象,暴露数据的过程就是给exports对象添加属性的过程
//b.js
let aModule = require('./a.js');
console.log(aModule.str);//andy
aModule.fn(10,20);//30
3.2 module.exports.xxx = xxx
//a.js
let name = 'andy';
function sum(a,b){
console.log(a + b);
}
module.exports.str = name;
module.exports.fn = sum;
//b.js
let aModule = require('./a.js');
console.log(aModule.str);//andy
aModule.fn(10,20);//30
或者直接给module.exports赋值
//a.js
function sum(a,b){
console.log(a + b);
}
module.exports = sum;
//b.js
const sum = require('./a.js');
sum(10,20);
3.3 global.xxx = xxx(不符合CommonJS规范,一般不使用这种方式)
//a.js
let name = 'andy';
function sum(a,b){
console.log(a + b);
}
global.str = name;
global.fn = sum;
//global为node中的全局对象,类比js中的window
//b.js
let aModule = require('./a.js');
console.log(global.str);//andy
global.fn(10,20);//30
exports和module.exports的区别?
不能直接给exports赋值,但是可以直接给module.exports赋值
(在开发中无论哪种方式都不要直接赋值,这种情况只会出现在面试题中)
let name = 'andy';
exports = name;//这种方式导入后拿不到数据,是个空对象{ }
module.exports = name;//这种方式导入后能拿到数据,‘andy’
//两者的区别在于:不能直接给exports赋值,但是可以直接给module.exports赋值
1.1require导入模块时可以不添加导入模块的类型
如果没有指定导入模块的类型, 那么会依次查找.js .json .node文件
无论是三种类型中的哪一种, 导入之后都会转换成JS对象返回给我们
1.2导入自定义模块时必须指定路径
require可以导入"自定义模块(文件模块)"、“系统模块(核心模块)”、“第三方模块”
导入"自定义模块"模块时前面必须加上路径
导入"系统模块"和"第三方模块"是不用添加路径
1.3导入"系统模块"和"第三方模块"是不用添加路径的原因
如果是"系统模块"直接到环境变量配置的路径中查找
如果是"第三方模块"会按照module.paths数组中的路径依次查找
导出数据:export { xxx };
导入数据:import { xxx } from ‘path’
注意点:
1.如果是通过export {xxx} 的方式导出数据,那么在导入接受数据的时候,接收的变量名必须和导出的变量名保持一致,
如果不一致则拿不到变量,究其原因,是因为在导入的时候的本质是ES6的解构赋值
//回顾解构赋值
let obj = {
name:'andy',
age:22
};
let {name,age} = obj;
console.log(name);
console.log(age);
2.如果是通过export {xxx} 的方式导出数据,又想在导入数据的时候修改接收的变量名称,那么可以使用as来修改,但是如果通过as修改了接收的变量名称,那么原有的的变量名称就会失效
//a.js
let name = 'zs';
export {name};
import {name} from './a.js'
console.log(name);
import {name as str} from './a.js'
console.log(str);//使用str时name失效
导出数据:export default xxx;
导入数据:import xxx from ‘path’
注意点:
1.如果是通过export default xxx 导出数据,那么接收的变量名可以和导出的变量名不一致
2.如果是通过export default xxx 导出数据,那么在模块中只能使用一次export default
//b.js
let name = 'zs';
export default name;
import name from './b.js'
import str from './b.js';
console.log(name);
console.log(str);//可以直接使用不同与导出时的变量名来接收
//c.js
let name = 'Ted';
let age = 12;
function say() {
console.log('hi');
}
class Person{
constructor(){
this.name = 'andy';
this.age = 22
}
}
export {name,age,say};
export default Person;
import Person,{name as str,age,say} from './c.js
let p = new Person();
console.log(p);
console.log(str);
console.log(age);
say();