学习笔记—Node中关于require的补充

日常的学习笔记,包括 ES6、Promise、Node.js、Webpack、http 原理、Vue全家桶,后续可能还会继续更新 Typescript、Vue3 和 常见的面试题 等等。


看过上一篇文章,我们对 require 的基本使用和其实现原理已经了解的差不多了。

通过对源码的学习,我们也会产生以下几个问题。

关于require的几个问题

首先,我们还是定义两个文件,一个导出一个引入。

1
2
3
4
5
6
// 使用 require 引入文件
// a.js
module.exports = "hello";
// b.js
let a = require('./a')
console.log(a); // hello

在上一篇源码分析的文章中,我们提到过这么一个点。

this = module.exports = exports (具体可以参考我上一篇文章 require的实现

那如果我们在这里输出 module.exports === exports ,结果又会如何呢?

module.exports、exports和this的关系

首先,我们先看一下上面那个问题的结果。

1
2
3
// a.js
console.log(module.exports === exports); // true
console.log(module.exports === this , exports === this); // true true

输出的结果是 true,我们还可以发现这三个值互换结果都是相等的。就是因为 this = module.exports = exports

既然他们三个是相等的,那么我是不是就可以直接 用 exports = "hello" 来输出结果了呢?

答案是不行。原因也很简单,因为我们在定义的时候是采用 let exports = module.exports = {} 的这种定义方式进行定义,文件在引用时,返回的是 module.exports 的值。 我们给 exports 赋值为 hello ,但 module.exports 依旧是空的。

1
2
3
4
5
6
// 大概意思,具体实现可参考源码
function require(){
let exports = module.exports = {};
exports = "hello";
return module.exports;
}

我们既然知道了这种赋值方式不行是因为值引用的问题,那么我们很快就可以想到。 是否可以利用堆栈内存的特性,给他们绑定一个属性呢?

1
2
3
4
5
6
7
// a.js
exports.a = "hello";
this.a = "hello";
module.exports.a = "hello";
// b.js
let a = require('./a')
console.log(a.a); // hello

我们发现,这三种形式都可以进行值的传递和引用。其含义就是 定义其堆内存中地址的值, 且修改堆的值的指向。

假设我们同时定义 module.exports 和 属性,那么结果会获取 module.exports 的值,不会获取属性。

(注:不能直接修改 this 的值,可能会发生一些错误)

1
2
3
4
5
6
// a.js
module.exports.a = "hello";
module.exports = "world";
// b.js
let a = require('./a')
console.log(a); // world

因为 module.exports优先级是最高的,因为最终还是将 module.exports导出。(所以 require 方法不支持多种写法同时导出)

module.exports的简化

看过上面的定义,我们可以简单整理一下 module.exports 的简化写法。

exports简化

我们现在需要将模块内的多个值导出。

1
2
3
4
5
6
7
// a.js
module.exports.a = "a";
module.exports.b = "b";
module.exports.c = "c";
// b.js
let result = require('./a')
console.log(); // { a: 'a', b: 'b', c: 'c' }

这样写会很麻烦,所以我们可以使用 exports 来进行简化

1
2
3
4
5
6
// a.js
exports.a = "a";
exports.b = "b";
exports.c = "c";
// b.js
// ... { a: 'a', b: 'b', c: 'c' }

就是对代码进行简化。

module.exports简化

现在有多个方法需要导出,我们就可以用下面的方式简写。

1
2
3
4
5
6
// a.js
module.exports = {
fn1(){},
fn2(){},
// ...
}

这种就是 module.exports 结合 ES6 的一种简写方式。

至此,我们的 Node的文件模块Node的核心模块 就总结完毕了。

下一篇文章我会总结一下 Node中第三方模块

本篇文章由莫小尚创作,文章中如有任何问题和纰漏,欢迎您的指正与交流。
您也可以关注我的 个人站点博客园掘金,我会在文章产出后同步上传到这些平台上。
最后感谢您的支持!

请打赏并支持一下作者吧~

欢迎关注我的微信公众号