---
title: 模块化语法参考
summary: "介绍小程序支持的 ESModule 和 CommonJS 模块化语法及模块引用规则。"
questions:
  - 小程序支持哪些模块化语法形式？
  - ESModule 中 export 命令有哪些使用方式？
  - 如何使用 import 命令加载其他模块？
  - CommonJS 中 module.exports 和 exports 有什么区别？
  - 模块的引用支持哪些路径方式？
  - 模块引用时文件名与文件夹名重名会有什么问题？
  - 模块引用有哪些注意事项？
  - 小程序是否支持 TypeScript 和 NPM？
---

# 模块化语法参考

小程序的逻辑代码使用 JavaScript 语法进行编写。可以将一些公共的代码抽离成为一个单独的 js 文件，作为一个模块，以实现逻辑共享复用。主要有 ESModule 和 CommonJS 两种形式。一个项目内应保持使用一种语法形式，否则可能出现导入异常的情况。

## ESModule 语法 (推荐)

ESModule 模块功能主要由两个命令构成：`export` 和 `import`。`export`命令用于规定模块的对外接口，`import` 命令用于输入其他模块提供的功能。

### export 命令

一个模块就是一个独立的文件。该文件内部的所有变量，外部无法获取。如果您希望外部能够读取模块内部的某个变量，就必须使用 `export` 关键字输出该变量。下面是一个 JS 文件，里面使用 `export` 命令输出变量。

```js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
```

上面代码是 profile.js 文件，保存了用户信息。ES6 将其视为一个模块，里面用 `export` 命令对外部输出了三个变量。

```js
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export { firstName, lastName, year };
```

上面代码在 `export` 命令后面，使用大括号指定所要输出的一组变量。它与前一种写法（直接放置在 `var` 语句前）是等价的，但是应该优先考虑使用这种写法。因为这样就可以在脚本尾部，一眼看清楚输出了哪些变量

`export` 命令除了输出变量，还可以输出函数或类（class）。

```js
export function multiply(x, y) {
  return x \* y;
};
```

上面代码对外输出一个函数 multiply。

更多详细 `export` 介绍，请参考 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/export

### import 命令

使用 `export` 命令定义了模块的对外接口以后，其他 JS 文件就可以通过 `import` 命令加载这个模块。

```js
// main.js
import { firstName, lastName, year } from './profile';

function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}
```

上面代码的 `import` 命令，用于加载 profile.js 文件，并从中输入变量。`import` 命令接受一对大括号，里面指定要从其他模块导入的变量名。大括号里面的变量名，必须与被导入模块（profile.js）对外接口的名称相同。

更多详细 `import` 介绍，请参考 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import

## CommonJS 语法

CommonJS 模块通过 `module.exports` 导出接口，`require` 命令导入。

`exports` 是 `module.exports` 的一个引用，因此在模块里边随意更改 `exports` 的指向会造成未知的错误。所以更推荐开发者采用 `module.exports` 来暴露模块接口，除非您已经清晰知道这两者的关系。

### module.exports 命令

模块只能通过 `module.exports` 或 `exports` 对外暴露接口。

```js
module.exports = {
  firstName: 'Michael',
  lastName: 'Jackson',
  year: '1958',
};
```

上面代码是 profile.js 文件使用 CommonJS 的写法。对外部输出了三个变量。

同样还可以输出函数或类（class）。

```js
module.exports = {
  multiply: function (x, y) {
    return x \* y;
  }
}
```

### require 命令

使用 `module.exports` 命令定义了模块的对外接口以后，其他 JS 文件就可以通过 `import` 命令加载这个模块。

```js
// main.js
const profile = require('./profile');

const { firstName, lastName, year } = profile;

function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}
```

上面代码的 `require` 命令，用于加载 profile.js 文件，并定义为 profile 变量。该变量等于 `module.exports` 的对象。

**注意** 不要在一个文件内出现不同的模块语法，应保持文件内只有一种语法，否则程序可能无法正常运行。

## 模块作用域

在 JS 模块文件中声明的变量和函数只在该模块内有效；不同的文件中可以声明相同名字的变量和函数，不会互相影响。

## 模块的引用

模块的应用支持绝对路径、相对路径、NPM 三方包。

```js
import a from '/absolute';
import b from './relative';
import pkg from 'lodash';
```

模块的引用应避免出现文件名与文件夹名重名的情况，除非您了解其中的差异。因此建议在使用绝对路径、相对路径时写全文件名路径。

```
├── foo
│   └──index.js
├── foo.js
```

```js
import foo from '/foo/'; // 引入 foo/index.js
import foo from '/foo/index'; // 引入 foo/index.js
import foo from '/foo'; // 引入 foo.js
```

**注意**

1. 模块引用的应保持大小写敏感，否则可能出现异常的情况。
2. 模块应避免循环引用如： a.js -> b.js -> c.js -> a.js。否则可能出现异常的情况。

## NPM 支持

智能小程序默认支持 NPM 生态。在根目录下创建 `package.json` 并通过 _npm_ _yarn_ 等包管理工具安装后的模块，即可在项目逻辑代码中引用。

## 高级进阶

### TypeScript 语法支持

JavaScript 是弱类型语言，为保障项目的质量，智能小程序默认支持使用 [TypeScript](https://www.typescriptlang.org/) 进行逻辑编写。
