关于node.js:moduleexports和exports应该用哪个

42次阅读

共计 3615 个字符,预计需要花费 10 分钟才能阅读完成。

在 Node.js 编程中,模块是独立的性能单元,能够在我的项目间共享和重用。作为开发人员,模块让咱们的生存更轻松,因为咱们能够应用模块来加强应用程序的性能,而无需亲自编写。它们还容许咱们组织和解耦代码,从而使应用程序更易于了解、调试和保护。

在这篇文章中,我将介绍如何在 Node.js 中应用模块,重点是如何导出和生产它们。

各种模块格局

因为 JavaScript 最后没有模块的概念,因而随着工夫的推移,呈现了各种相互竞争的格局。上面列出了须要留神的次要格局:

  • Asynchronous Module Definition (AMD)格局用于浏览器,应用 define 函数来定义模块。
  • CommonJS (CJS)格局用于 Node.js,应用 requiremodule.exports来定义依赖和模块。npm 生态系统就是基于这种格局构建的。
  • ES Module (ESM)格局。从 ES6(ES2015)开始,JavaScript 反对原生模块格局。它应用 export 关键字导出模块的公共 API,应用 import 关键字导入模块。
  • System.register 格局用于反对 ES5 中的 ES6 模块。
  • Universal Module Definition (UMD)格局能够用于浏览器和 Node.js。当一个模块须要被多个不同的模块加载器导入时,它就会十分有用。

请留神,本文仅波及 Node.js 的规范 CommonJS格局。

引入模块

Node.js 带来了一系列内置模块,这样咱们就能够间接在代码中应用而不须要装置它们。要应用它们,咱们须要应用 require 关键字引入模块,并赋值给变量。而后就能够用它来调用模块公开的任何办法。

举个例子,要列举出目录下的内容,能够应用文件系统模块,以及该模块的 readdir 办法:

const fs = require('fs');
const folderPath = '/home/jim/Desktop/';

fs.readdir(folderPath, (err, files) => {
  files.forEach(file => {console.log(file);
  });
});

请留神,在 CommonJS 中,模块是同步加载的,并依照模块呈现的程序进行解决。

创立并导出模块

当初,让咱们看看如何创立本人的模块并导出它。创立 user.js 文件并增加下列代码:

const getName = () => {return 'Jim';};

exports.getName = getName;

而后在同一文件夹下创立index.js,并增加下列代码:

const user = require('./user');
console.log(`User: ${user.getName()}`);

应用 node index.js 运行代码,你会在终端上看到下列输入:

User: Jim

产生了啥?好吧,如果你查看 user.js 文件,你会留神到咱们定义了一个 getName 函数,而后应用 exports 关键字让它在任意导入的中央可用。在 index.js 中,咱们导入了该函数并执行了它。还须要留神 require 语句,该模型名称有着 ./ 前缀,意味着它是本地文件。还要留神的是,此处不须要增加文件扩展名。

导出多个办法和值

咱们能够用同样的形式导出多个办法和值:

const getName = () => {return 'Jim';};

const getLocation = () => {return 'Munich';};

const dateOfBirth = '12.01.1982';

exports.getName = getName;
exports.getLocation = getLocation;
exports.dob = dateOfBirth;

index.js 中这么应用:

const user = require('./user');
console.log(`${user.getName()} lives in ${user.getLocation()} and was born on ${user.dob}.`
);

上述代码的产出是:

Jim lives in Munich and was born on 12.01.1982.

留神咱们给导出的 dateOfBirth 变量起的名字能够是任何咱们喜爱的名字(本例中为 dob)。它不用与原始变量名雷同。

语法的变动

我还应该提到,能够在导出过程中导出办法和值,而不仅仅是在文件开端导出。

举个例子:

exports.getName = () => {return 'Jim';};

exports.getLocation = () => {return 'Munich';};

exports.dob = '12.01.1982';

多亏了解构赋值,咱们能够筛选想要导入的办法:

const {getName, dob} = require('./user');
console.log(`${getName()} was born on ${dob}.`
);

导出默认值

下面的示例中,咱们独自导出了函数和值。这对于整个应用程序都可能须要的辅助函数来说十分不便,但当你有一个只导出一样货色的模块时,应用 module.exports 会更常见:

class User {constructor(name, age, email) {
    this.name = name;
    this.age = age;
    this.email = email;
  }

  getUserStats() {
    return `
      Name: ${this.name}
      Age: ${this.age}
      Email: ${this.email}
    `;
  }
}

module.exports = User;

index.js 中:

const User = require('./user');
const jim = new User('Jim', 37, 'jim@example.com');

console.log(jim.getUserStats());

代码输入如下:

Name: Jim
Age: 37
Email: jim@example.com

module.exports 和 exports 的区别

在开源世界里,你能够会遇到下列语法:

module.exports = {getName: () => {return 'Jim';},

  getLocation: () => {return 'Munich';},

  dob: '12.01.1982',
};

在这里,咱们将想要导出的函数和值调配给 module 上的 exports 属性,当然,这样做成果很好:

const {getName, dob} = require('./user');
console.log(`${getName()} was born on ${dob}.`
);

那么,module.exportsexports 的不同之处是什么?一个只是另一个的别名吗?

有点,但不齐全是……

为了说明我的意思,咱们更改 index.js 中的代码,打印 module 的值:

console.log(module);

输入如下:

Module {
  id: '.',
  exports: {},
  parent: null,
  filename: '/home/jim/Desktop/index.js',
  loaded: false,
  children: [],
  paths:
   [ '/home/jim/Desktop/node_modules',
     '/home/jim/node_modules',
     '/home/node_modules',
     '/node_modules' ] }

正如你看到的,module有一个 exports 属性。在 exports 上增加一些货色:

// index.js
exports.foo = 'foo';
console.log(module);

输入如下:

Module {
  id: '.',
  exports: {foo: 'foo'},
  ...

exports 调配的属性也会将它们增加到 module.exports。这是因为(至多最后)exports 是对 module.exports 的援用。

应该用哪个

因为 module.exportsexports 都指向同一个对象,因而应用哪个通常并不重要。例如:

exports.foo = 'foo';
module.exports.bar = 'bar';

这段代码将导致模块的导出对象为 {foo: 'foo', bar: 'bar'}

不过,有一个注意事项。无论你将什么赋值给 module.exports,都将从你的模块中导出什么。

那么,请看上面的内容:

exports.foo = 'foo';
module.exports = () => { console.log('bar'); };

这样只会导出一个匿名函数。foo 变量将被疏忽。

总结

模块已成为 JavaScript 生态系统不可或缺的一部分,它使咱们可能将较小的局部组成大型程序。我心愿本文能为你介绍如何在 Node.js 中应用模块,并帮忙你揭开模块语法的神秘面纱。

以上就是本文的全部内容,如果对你有所帮忙,欢送点赞、珍藏、转发~

正文完
 0