随着应用程序和代码库的增长,保持代码的可维护性和模块化变得越来越重要。模块模式允许将代码分成更小的、可重用的部分。
除了能够将代码分割成更小的可重用部分之外,模块还允许将文件中的某些值保留为私有。默认情况下,模块内的声明范围(封装)为该模块。如果我们不显式导出某个值,那么该值在该模块之外不可用。这降低了在代码库的其他部分声明的命名冲突的风险,因为这些值在全局作用域中不可用。
ES2015引入了内置的JavaScript模块。模块是一个包含JavaScript代码的文件,与普通脚本相比在行为上有一些不同。
让我们看一个名为math.js的模块示例,其中包含数学函数。
// math.js
function add(x, y) {
return x + y;
}
function multiply(x) {
return x * 2;
}
function subtract(x, y) {
return x - y;
}
function square(x) {
return x * x;
}
// index.js
console.log(add(2, 3));
console.log(multiply(2));
console.log(subtract(2, 3));
console.log(square(2));
math.js 中定义了四个函数add
,multiply
,subtrack
,square
,我们想要在index.js中调用这几个函数。直接运行的话,会报错:Uncaught ReferenceError ReferenceError: add is not defined
。
为了使index.js能调用到math.js中的函数,则需要先将这几个函数导出。使用关键词export
将函数导出。
// math.js
export function add(x, y) {
return x + y;
}
export function multiply(x) {
return x * 2;
}
export function subtract(x, y) {
return x - y;
}
export function square(x) {
return x * x;
}
仅仅将math.js中的函数export还不够,还需要在index.js中,将需要调用的函数导入。
// index.js
import { add, multiply, subtract, square } from "./math.js";
接下来,我们在运行一下,看看效果:
直接运行报错了。在node.js环境下,按上述简单的代码构成是不够的。
解决方案
1. npm init -y
2. 在package.json中添加"type": "module",
我的代码结构如下:
再次运行,结果如下:
可以看到,math.js中的4个显示声明的函数可以导出,index.js中也能正常导入这四个函数,并正常调用。
接下来,我们尝试下,如果在math.js中的变量不声明为export,看index.js是否还可以调用。
显然和我们预想的一致,不会奏效。
通过将值保留为模块私有,可以降低意外污染全局作用域的风险。不必担心模块使用者会意外覆盖模块内部的变量的值,这些变量可能与模块的私有变量具有相同的名称:它可以防止命名冲突。
如果从模块导出的命名和当前文件的本地命名有冲突,怎么解决呢?
可以通过as
关键字重命名被导入的函数名。
上述代码将add
和multipy
重命名为addValues
和multiplyValues
。消除了命名冲突问题。
除了有我们上述代码中使用的命名导出外,还有默认导出。
在math.js中将add
函数声明为export default
,可以在index.js中直接调用。如果默认导出的函数有命名冲突的话,可以直接在index.js中重命名