NodeJs exports 对比 module.exports

导语

他们是什么,如何使用它们以及如何使用它们。
(请注意,本文是在Node.js 6.1.0发行之后编写的)

长话短说

  • 将module.exports视为从require()返回的变量。默认情况下,它是一个空对象,更改为任何内容都可以。
  • exports 本身永远不返回,它只是对module.exports的引用;一个方便的变量,帮助模块作者编写更少的代码。使用其属性是安全和推荐的。
    1
    2
    3
    exports.method = function() {…} 
    vs.
    module.exports.method = function() {…}

简单的模块示例

首先,我们需要一个示例代码库。我们从一个简单的计算器开始:

1
2
// calculator.js
module.exports.add = (a,b) => a+b

用法

1
2
3
// app-use-calculator.js
const calculator = require('./calculator.js')
console.log(calculator.add(2,2)) // 打印 4

模块包装

Node.js用函数包装器内部包装所有require()模块

1
2
3
4
5
6
(function (exports, require, module, __filename, __dirname) {

// calculator.js is actually executed here
module.exports.add = (a,b) => a+b

});

模块对象

变量module是表示当前模块的对象。它是每个模块局部的,也是私有的(只能从模块代码访问):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// calculator-printed.js

module.exports.add = (a,b) => a+b

console.log(module)

/*
当调用此模块: require('./calculator-printed.js') log 打印:
Module {
id: '/Users/laz/repos/module-exports/calculator-printed.js',
exports: { add: [Function] },
parent:
Module { ... }
filename: '/Users/laz/repos/module-exports/calculator-printed.js',
loaded: false,
children: [],
paths: [ ... ]
}

Module.exports

  • 它是从require()调用中返回对象的引用。
  • 它由Node.js自动创建。
  • 它只是一个普通JavaScript对象的引用。
  • 默认情况下也是空的(我们的代码附加一个“add()”方法)

有两种方法可以使用module.exports:

1.附加公共方法(如我们在计算器示例中所做的那样)。
2.用我们的自定义对象或函数替换它。

为什么要更换?替换时,我们可以返回任何其他类的任意实例。这是ES2015中的一个例子:

1
2
3
4
5
// calculator-base.js
module.exports = class Calculator {
add(a,b) { return a + b }
substract(a,b) { return a - b }
}

以上,“calculator-base” 导出 一个类。
让我们扩展“Calculator”类,这次导出一个实例:

1
2
3
4
5
6
7
8
9
10
// calculator-advanced.js

const Calculator = require('./calculator-base.js')

class AdvancedCalculator extends Calculator {
multiply(a,b) { return a * b }
divide(a,b) { return a / b }
}

module.exports = new AdvancedCalculator()

用法

导出别名

  • exports只是一个方便变量,因此模块作者可以编写更少的代码
  • 使用其属性是安全和推荐的。(如: exports.add = function…)
  • 导出不返回require()module.exports可以!)

这里有一些不错的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// calculator-exports-examples.js

// good
module.exports = {
add(a,b) { return a+b }
}

// good
module.exports.subtract = (a,b) => a-b

// 有效
exports = module.exports

// good 只是一个较短版本的代码

exports.multiply = (a,b) => a*b

// bad, 不允许这样做
exports = {
divide(a,b) { return a/b }
}

注意:通常的做法是用自定义函数或对象来替换module.exports。如果我们这样做,但仍然想继续使用exports简写;那么exports必须重新指向我们新的自定义对象:

1
2
exports = module.exports = {}
exports.method = function() {...}

结论

一个名为export的变量尚未完全导出的是令人困惑的,特别是对于Node.js的新手。即使官方文件也有一点点奇怪的含义:

As a guideline, if the relationship between exports and module.exports seems like magic to you, ignore exports and only use module.exports.

我认为代码不是魔术。开发人员应该更深入地了解他们使用的平台和语言。通过这样做;程序员获得了有价值的信心和知识,从而对代码质量、系统架构和生产力产生了积极的影响。

相关文章:

本文原地址 Node.js module.exports vs. exports
作者:lazlojuly 翻译不到位还请指正

推荐文章