关于模块化的想法

198 阅读3分钟

一、为什么要模块化

在开发过程中,代码越写越长就容易出现一个难以维护的问题,所以为了编码的可维护性,就把很多函数分组,分别放不同的文件里,这样每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。(一个js文件就是一个模块)

使用模块的好处:

提高代码的可维护性;编写代码不必从零开始,当一个模块编写完成,就可以被其它地方引用。编程的时候经常引用到向nodejs内置的模块和来自第三方的模块;

可以避免函数名和变量名冲突,相同名字的函数和变量完全可以分别存在不同的模块中,因此在编写模块时,不必考虑名字会与其他模块冲突。

主要原因就是方便项目的开发和维护

二、(面试题)模块规范的定义

一个js文件就是一个模块,模块的作用域是私有的,内部定义的变量或者函数,只有当前文件(模块)可以使用。如果别人需要使用我们模块里面的东西,要实现以下两点:

1.自己写的模块由于模块作用域是私有的,默认情况下,外部是没有办法使用的,如果希望别人可以使用,则需要导出exports或者module.exports,导出的时候,以对象的方式进行导出。

2.别人要使用某个模块,则需要先引入该模块,使用require引入,引入后需要使用一个变量来接受导入的对象。

对书写格式和交互规则的详细描述,就是模块定义规范(Module Definition Specification):

AMD规范:Require.js

CMD规范:Sea.js

CommonJS的Modules规范:NodeJs

ES6模块化规范:import...from...

三、关于CommonJS模块化使用

导出数据方式一:

exports.num = num;
exports.sum = sum;
exports.Animal = Animal;

导出数据方式二:

//通过module.exports等于一个对象,来导出数据
//对象可采用es6简化对象的写法
module.exports={
num,
sum,
Animal
};

导入数据:

//使用某个模块的数据,需要使用require关键字来导入
//在导入用户自己开发的模块的时候,需要加上路径(相对路径、绝对路径)注意:./ 必须协商
//模块文件的扩展名、后缀名可以写或不写
//导出的模块一般需要使用一个变量来接收,一般把接受的量定义为常量
//定义常量的名称和文件的名称保持一致(非必须,但尽量这样做,避免变量名过多在后续的代码中产生出入)
const sd1 = require('./modules/sd1.js');

完整代码:

//sd1.js
let num = 10;
function sum(a,b){
return a+b
}

class Animal{
constructor(){
this.age = 0;
}
}

//导出数据方式1:
//exports.num = num;
//exports.sum = sum;
//exports.Animal = Animal;

//模块的使用.js
const sd1 = require('./modules/sd1.js');

console.log(sd1);//{num:10,sum:[Function:sum],Animal:[Function:Animal]}
console.log(sd1.sum(10,20));//30
const obj = new sd1.Animal();
console.log(obj.age);//0

四、ES6模块化的使用

node在13.2版本以下不支持ES6模块化语法,13.2版本以上开始支持ES6模块化语法,但是模块化后缀名必须是.mjs。

导入和导出方式都有两种:分别是按需导出和默认导出。

sd2.mjs文件中:

//第一种导出方式:按需导出
export let name = 'nodejs';
export let age = 11;
export function func(){
console.log('sd1中的func函数执行了!');
}
export class Animal{
constructor(){
this.age = 30;
}
}
//第一种到处方式注意 1.支持写多个export 2.导出变量必须写let 或者var
-----------------------------------------------------------------------

class Animal2{
constructor(){
this.age = 22;
}
}
//第二种导出方式:默认导出
export default{
aa:'aa',
bb:'bb',
cc:'cc',
dd(){
console.log('执行了dd');
},
Animal2
}
//第二种导出方式注意点:
//1.export default在同一个文件只能书写一次,一般以对象导出
//2.导出时候只能先定义再导出,不可边定义边导出。(不能这么写:export default let a = 9;)

ES6模块化导入使用.mjs文件中:

//第一种:按需导入
import {name,age,func,Animal} from "./modules/sd2.mjs"

console.log(name);
console.log(age);
func();
let ani = new Animal()
console.log(ani.age);

console.log("以下为第二种方式导入-------------");

import sd2 from "./modules/sd2.mjs"
console.log(sd2);
console.log(sd2.aa);
console.log(sd2.bb);
console.log(sd2.cc);
sd2.dd();
let ani2 = new sd2.Animal2()
console.log(ani2.age);