module.exports和exports,应该用哪个

module,exports,应该,哪个 · 浏览次数 : 127

小编点评

**模块介绍** 模块是 Node.js 中一个独立的功能单元,可用于增强应用程序的功能,而无需手动编写。模块允许我们组织和解耦代码,使其更容易理解、调试和维护。 **导出和消费模块** 在 Node.js 中,我们可以导出模块的公共 API,并使用 `require` 关键字导入它们。模块可以包含多个方法和值,可以使用 `exports` 对象导出。 **创建和导出模块** * 创建一个 `user.js` 文件并添加以下代码: ```javascript const getName = () => { return 'Jim'; }; exports.getName = getName; ``` * 创建 `index.js` 文件并添加以下代码: ```javascript const user = require('./user'); console.log(`User: ${user.getName()}`); ``` **使用模块** 在 `index.js` 中,我们可以使用 `require` 导入 `user` 模块并执行 `getName` 方法: ```javascript const user = require('./user'); console.log( `${user.getName()} was born on ${user.dob}.` ``` **模块格式** * CommonJS (CJS) 格式:使用 `require` 和 `module.exports` 来导出和导入模块。 * ES Module (ESM) 格式:使用 `export` 和 `import` 语句来导出和导入模块。 * Node.js 标准格式:使用 `module.exports` 对象来导出和导入模块。

正文

在 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 中使用模块,并帮助你揭开模块语法的神秘面纱。

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

与module.exports和exports,应该用哪个相似的内容:

module.exports和exports,应该用哪个

> 在 Node.js 编程中,模块是独立的功能单元,可以在项目间共享和重用。作为开发人员,模块让我们的生活更轻松,因为我们可以使用模块来增强应用程序的功能,而无需亲自编写。它们还允许我们组织和解耦代码,从而使应用程序更易于理解、调试和维护。 在这篇文章中,我将介绍如何在 Node.js 中使用模块

[转帖]Spring Boot 3 Ships November 2022, Delays Java Module Support

Spring Boot 3 Ships November 2022, Delays Java Module Supporthttps://www.infoq.com/news/2022/10/spring-boot-3-jax-london/ Join a community of experts.

[转帖]Module ngx_http_v2_module

https://nginx.org/en/docs/http/ngx_http_v2_module.html#:~:text=Sets%20the%20maximum%20number%20of%20concurrent%20HTTP%2F2%20streams,limit%20applies%20

module 'numpy' has no attribute 'int'.

原因:np.int 在 NumPy 1.20 中已弃用,在 NumPy 1.24 中已删除 AttributeError: module 'numpy' has no attribute 'int'. `np.int` was a deprecated alias for the builtin `

[转帖]nginx的map指令

一 ngx_http_map_module模块 1) map 指令是由 'ngx_http_map_module 模块'提供的,默认情况下安装 nginx 都会'安装'该模块. 2) map 的主要作用是'创建自定义变量',通过使用 nginx 的'内置'变量,去'匹配'某些特定规则;如果匹配成功则

[转帖]超详细的解决ModuleNotFoundError: No module named '_curses'错误的方法!!!

超详细的解决ModuleNotFoundError: No module named '_curses’的错误 问题描述:在写py脚本时,需要用到curses库(提供了控制字符屏幕的独立于终端的方法)。 导入的时候完全正常 Run的时候却报了这样的错误(它说找不到这个包) 本能的解决方法: 首先想到

[转帖]Nginx之ngx_http_realip_module

https://www.jianshu.com/p/80a779b3bf20 问题描述 今日在线上查询nginx日志文件的用户真实IP时,发现remote_addr和XFF地址一模一样,这点让我很是不理解,正常来讲remote_addr应该获取到的是上一个节点转发的IP地址,我们却是获得了用户的真实

[转帖]nginx上传模块—nginx upload module-

https://www.cnblogs.com/lidabo/p/4171515.html 一. nginx upload module原理 官方文档: http://www.grid.net.ru/nginx/upload.en.html Nginx upload module通过nginx服务来

一文带你了解 JS Module 的始末

写在前面 模块化开发是我们日常工作潜移默化中用到的基本技能,发展至今非常地简洁方便,但开发者们(指我自己)却很少能清晰透彻地说出它的发展背景, 发展过程以及各个规范之间的区别。故笔者决定一探乾坤,深入浅出学习一下什么是前端模块化。 通过本文,笔者希望各位能够收获到: 前端模块化发展的大致历史背景 �

GO 项目依赖管理:go module总结

转载请注明出处: 1.go module介绍 go module是go官方自带的go依赖管理库,在1.13版本正式推荐使用 go module可以将某个项目(文件夹)下的所有依赖整理成一个 go.mod 文件,里面写入了依赖的版本等 使用go module之后我们可不用将代码放置在src下 使用 g