Node.js中的module.exports和exports,在 Node.js 编程中,模块是独立的功能单元,可以在项目之间共享和重用。它们使我们作为开发人员的生活更轻松,因为我们可以使用它们来增强我们的应用程序,而无需我们自己编写的功能。它们还允许我们组织和分离我们的代码,从而使应用程序更易于理解、调试和维护。

在本文中,将研究如何使用Node.js中的模块,重点是如何导出和使用它们。

不同的Node.JS模块格式

由于JavaScript最初没有模块的概念,随着时间的推移出现了各种竞争格式。以下是需要注意的主要事项列表:

  • 异步模块定义 (AMD) 格式在浏览器中使用,并使用函数来定义模块。define
  • CommonJS(CJS)格式用于Node.js并使用和定义依赖项和模块。npm 生态系统就是建立在这种格式之上的。requiremodule.exports
  • ES 模块 (ESM) 格式。从ES6(ES2015)开始,JavaScript支持原生模块格式。它使用关键字导出模块的公共 API,并使用关键字导入模块。exportimport
  • System.register格式旨在支持ES6中的ES5模块。
  • 通用模块定义 (UMD) 格式既可以在浏览器中使用,也可以在 Node.js 中使用。当模块需要由许多不同的模块加载器导入时,它很有用。

请注意,本文仅涉及 CommonJS 格式,即 Node.js 中的标准。如果你想阅读任何其他格式,我推荐这篇文章,作者是SitePoint作者Jurgen Van de Moere。

需要的模块

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关键字使其可用于其他地方的导入。然后在.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.

语法变化

我还应该提到,不只是在文件末尾,还可以随时随地导出方法和值。

例如:

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}.`
);

正如您所料,此日志记录:

Jim was born on 12.01.1982.

导出默认值

在上面的示例中,我们分别导出函数和值。这对于应用程序中可能需要的助手函数来说很方便,但是当你有一个只导出一个东西的模块时,使用它更常见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有什么区别?

在浏览 Web 的过程中,您可能会遇到以下语法:

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

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

  dob: '12.01.1982',
};

这里,我们将要导出的函数和值分配给exports上的属性module。

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

这会记录以下内容:

Jim was born on 12.01.1982.

那又怎么样两者之间的差异module.exports和exports? 一个只是另一个的方便别名吗?

嗯,有点,但不完全…

为了说明我的意思,让我们更改中的代码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属性。让我们添加一些内容:

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

该输出:

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

将属性分配给exports还将它们添加到 module.exports这是因为(至少在最初)exports是对的引用module.exports .

那么我应该使用哪一个?

作为module.exports出口两者都指向同一个对象,通常使用哪个对象并不重要。例如:

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

此代码将导致模块的导出对象{ foo: 'foo', bar: 'bar' } .

然而,有一个警告。分配到module.exports的内容就是从模块导出的内容。

因此,采取以下措施:

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

这只会导致导出匿名函数。这个foo变量将被忽略

Node.js中的module.exports和exports的总结

模块已经成为JavaScript生态系统不可或缺的一部分,允许我们用较小的部分组成大型程序。我希望本文能很好地介绍如何在Node.js中使用它们,并帮助您揭开它们语法的神秘面纱。

相关推荐

如何使用GPT-4审查和重构代码

Vue与React的选择

领券有优惠