# 模块化

在开发过程中，你可以将一些公共代码抽离，保存在一个 js 文件里作为独立的模块。该模块只有通过 `module.exports` 或者 `exports` 才可以对外暴露接口。

## module.exports 和 exports 注意事项

`exports` 是 `module.exports` 的一个引用，因此在模块中随意修改 `exports` 的指向，会造成未知的错误。基于该问题，除非你已明确 `module.exports` 和 `exports` 的关系，否则推荐你采用 `module.exports` 来暴露模块接口。

```js
// common.js
function hello(name) {
  console.log(`Hello ${name}!`);
}
function goodbye(name) {
  console.log(`Goodbye ${name}!`);
}

module.exports.hello = hello;
exports.goodbye = goodbye;
```

在需要引用这些模块的文件中，使用 `require(path)` 将公共代码引入。

- 如果该文件是自己本地项目下的模块，则 path 需要为相对路径。

```js
    // index.js 
    const common = require('./common.js') // common.js 在与 index.js 同级 的目录下
    Page({
      helloWorld: function() {
        common.hello('world')
      },
      goodbyeWorld: function() {
        common.goodbye('world')
      }
    })
    ```

- 如果引用了 node_modules 里的包，则 path 为包的名称即可，无需写相对路径。

使用前需要开启 npm 能力，详情参见 [npm 支持](https://open.feishu.cn/document/uYjL24iN/uEzMzUjLxMzM14SMzMTN/npm-support)。

```js
    const sm2 = require('miniprogram-sm-crypto').sm2 // miniprogram-sm-crypto 为三方包
    const { publicKey, privateKey } = sm2.generateKeyPairHex();
    Page({
      data: {
        publicKey: publicKey,
        privateKey: privateKey
      }
    })
    ```

## 文件作用域

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

如果需要全局访问某些信息，则可以将这些信息在 `App()` 中进行设置，然后
在需要的时候通过函数 `getApp()` 获取全局的应用实例，以获得挂载在实例上的信息。例如：

1. 在 app.js 文件的 App() 中定义信息。

```javascript
    // app.js
    App({
      globalData: 1
    })
    ```

2. 在 a.js 中获取信息。

```javascript
    // a.js
    const app = getApp();
    app.globalData++;
    ```

3. 在 b.js 中的获取信息。

```javascript
    // b.js 
    // 如果 a.js 已经在 b.js 前加载过，那么此时 globalData 应该为 2
    console.log(getApp().globalData);
    ```