zoukankan      html  css  js  c++  java
  • 学习笔记—Node中关于require的补充

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


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

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

    关于require的几个问题

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

    // 使用 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的关系

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

    // 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 依旧是空的。

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

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

    // 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 的值,可能会发生一些错误)

    // 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简化

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

    // 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 来进行简化

    // a.js
    exports.a = "a";
    exports.b = "b";
    exports.c = "c";
    // b.js
    // ...  { a: 'a', b: 'b', c: 'c' }
    

    就是对代码进行简化。

    module.exports简化

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

    // a.js
    module.exports = {
      fn1(){},
      fn2(){},
     	// ...
    }
    

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

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

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

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

  • 相关阅读:
    Qt中的串口编程之一
    Qt Q_DECLARE_METATYPE说明——让自定义的类型设置到QVariant
    Qt中Pro文件变量详细说明
    C++/C语言的标准库函数与运算符的区别new/delete malloc/free
    View与Model绑定注意事项 (视图无数据显示)
    (五)Qt实现自定义模型基于QAbstractItemModel
    (四)Qt实现自定义模型基于QAbstractTableModel (一般)
    (三)使用预定义模型QDirModel的例子
    (二)使用预定义模型 QStringListModel例子
    (一) Qt Model/View 的简单说明
  • 原文地址:https://www.cnblogs.com/moxiaoshang/p/15586660.html
Copyright © 2011-2022 走看看