浅谈Node中的模块化

2023-11-12

  关于这篇文章早在去年年初的时候我就想写一片关于模块化的文章,但是推到现在才来完成也有很多好处,巩固之前对Node的理解。毕竟在我目前的项目中还没有一款项目是用到了Node开发,所以导致我对Node的一些基本知识已经忘记。

一、什么是模块化

现实生活中的模块化例子, 手机组装: 摄像头、话筒、听筒、显示器、电池。。。。。。

非模块化开发的问题 :

1、命名冲突,比如全局污染。。。;

2、文件依赖,团队变大后,维护大量的文件依赖关系非常困难,公共模块的维护、升级很不方便团队变大后,维护大量的文件依赖关系非常困难,公共模块的维护、升级很不方便;

3、可维护性低等等。

二、模块化的演变过程

  从最简单的加减乘除运算来举例说明,为了方便理解这里都没有采用ES6的语法。

1、全局函数的方式——最原始的写法

    // 早期的开发过程中就是将重复使用的代码封装到函数中
    // 再将一系列的函数放到一个文件中,称之为模块
    // 缺点:存在命名冲突,可维护性也不高的问题
    // 仅仅从代码角度来说:没有任何模块的概念
    function convertor(a) {
        return parseFloat(a);
    }

    function add(a, b) {
        return convertor(a) + convertor(b);
    }
    

2、封装对象的方式

    // 有了传统编程语言中的命名空间
    // 从代码层面就已经有了模块的感觉
    // 避免了多处全局污染
    // 缺点:没有私有空间,没有抽离私有成员
    var calculator = {
        add: function (a, b) {
            return this.convertor(a) + this.convertor(b);
        },
        convertor:function(a){
            return parseFloat(a)
        }
    };

3、私有空间的划分

    // 这里形成一个单独的私有的空间
    // 高内聚,低耦合:模块内部相关性强,模块之间没有过多相互牵连,如convertor和add
    // 缺点:可扩展性低
    var calculator = (function () {
        // 将一个成员私有化,外部无法访问和修改
        function convertor(a) {
            return parseFloat(a);
        }
        // 抽象公共方法(其他成员中都会用到的)
        function add(a, b) {
            return convertor(a) + convertor(b);
        }
        return {
            add:add
        }
    })();

4、模块的扩展

  // calc_v2016.js
  (function (window,calculator) {
    function convert(input) {
      return parseFloat(input);
    }
    calculator = {
      add: function (a, b) {
        return convert(a) + convert(b);
      }
    }
    window.calculator = calculator;
  })(window, {});

  // 新增需求 remain
  // calc_v2017.js
  // 开闭原则:对新增开放,对修改关闭
  (function (calculator) {
    function convert(input) {
      return parseInt(input);
    }
    // calculator 如果存在的话,我就是扩展,不存在我就是新加
    calculator.remain = function (a, b) {
      return convert(a) % convert(b);
    }
    window.calculator = calculator;
  })(window.calculator || {});

5、第三方依赖

  // calc_v2016.js
  (function (window,calculator) {
    //对全局产生依赖,不能这样用
    console.log(document);
    function convert(input) {
      return parseFloat(input);
    }
    calculator = {
      add: function (a, b) {
        return convert(a) + convert(b);
      }
    }
    window.calculator = calculator;
  })(window, {});

  // 新增需求
  // calc_v2017.js
  (function (calculator,document) {
    // 依赖函数的参数,是属于模块内部
    console.log(document);
    function convert(input) {
      return parseInt(input);
    }
    calculator.remain = function (a, b) {
      return convert(a) % convert(b);
    }
    window.calculator = calculator;
  })(window.calculator || {},document);

  以上通过一些简短的代码介绍了模块化发展大致情况。

三、模块化规范

1、服务器端规范

   CommonJS---nodejs

2、浏览器端规范

  AMD---RequireJS 国外相对流行(http://www.requirejs.cn/)

  CMD---SeaJS 国内相对流行(http://seajs.org/)

3、ES6的module规范

在这里就不具体展示每种规范的具体写法了。

四、CommonJS规范

1、Node 采用的模块化结构是按照 CommonJS 规范

模块与文件是一一对应关系,即加载一个模块,就是加载对应的一个模块文件;

CommonJS 就是一套约定标准,不是技术; 用于约定我们的代码应该是怎样的一种结构;

2、CommonJS 模块的特点

所有代码都运行在模块作用域,不会污染全局作用域;

模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。module.exports不会再次执行该模块;

模块加载的顺序按照其在代码中出现的顺序;

3、模块的分类

自定义模块:就是我们自己写的功能模块文件。

核心模块:Node 平台自带的一套基本的功能模块。

第三方模块:社区或第三方开发好的功能模块,可以直接拿回来用。

4、模块的定义

(1)Node 内部提供一个 Module 构建函数。所有模块都是 Module 的实例,属性如下:

  module.id 模块的识别符,通常是带有绝对路径的模块文件名。

  module.filename 模块定义的文件的绝对路径。

  module.loaded 返回一个布尔值,表示模块是否已经完成加载。

  module.parent 返回一个对象,表示调用该模块的模块。

  module.children 返回一个数组,表示该模块要用到的其他模块。

  module.exports 表示模块对外输出的值。

(2)载入一个模块就是构建一个 Module 实例,一个新的 JS 文件就是一个模块

  导出方式:module.exports 和 exports

  exports.name = value;

  module.exports = { name: value };

  module.exports 是用于为模块导出成员的接口;

  exports 是指向 module.exports 的别名,相当于在模块开始的时候执行:var exports = module.exports。

5、用Node手写一个简单的require

function $require(files) {
    const fs = require('fs');
    const path = require('path');
    let filename = path.join(__dirname, files);
   //注意,这里实现的缓存不是Node的缓存机制 $require.cache
=$require.cache||{}; if($require.cache[filename]) return $require.cache[filename].exports; let dirname=path.dirname(filename); let file = fs.readFileSync(filename); let module = { id:filname, exports: {} }; //保存module.exports重新赋值前的值 let exports = module.exports; let code = `(function (module,exports,__dirname,__filename) { ${file} })(module,exports,dirname,filename)`; eval(code); $require.cache[filename]=module; return module.exports; }
五、Node加载文件规则

Node 使用 CommonJS 模块规范,内置的 require 函数用于加载模块文件。

require 的基本功能是,读入并执行一个 JavaScript 文件,然后返回该模块的 exports 对象。 如果没有发现指定模块,会报错。

require 加载文件规则:

(1)require 加载js文件时可以省略扩展名;可以直接加载json文件;

(2)通过 ./ 或 ../ 开头:则按照相对路径从当前文件所在文件夹开始寻找模块;

    require('../file.js'); => 上级目录下找 file.js 文件

(3)通过 / 开头:则以系统根目录开始寻找模块;

    require(‘/Web/Vue/vue-full/src/main.js'); => 以绝对路径的方式找;

(4)如果 require 传入的是一个目录的路径,会自动查看该目录的 package.json 文件,然后加载 main 字段指定的入口文件;

(5)如果package.json文件没有main字段,或者根本就没有package.json文件,则默认找目录下的 index.js 文件作为模块;

(6)如果参数字符串不以“./“ 或 ”/“ 开头,则表示加载的是一个默认提供的核心模块(位于 Node 的系统安装目录(node_modules)中;

(7)缓存文件的加载优先级最高,同名的系统模块要比自定义模块优先级高;

(8)Node在加载系统模块的时候,如果当前文件夹里面没有node_modules文件夹就会去逐层向上查找至项目根目录直到找到为止,如果没有就会报错。

六、总结

以上就是我对模块化加载的理解,当然这里没有去过多的写案例,目的是为了以后回来查阅方便,方便自己记忆。

 

转载于:https://www.cnblogs.com/onebox/p/9752239.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅谈Node中的模块化 的相关文章

  • 职工管理系统(C++)

    职工管理系统有以下8个功能 增加职工信息 实现批量添加职工功能 将信息录入到文件中 职工信息为 职工编号 姓名 部门编号 显示职工信息 显示公司内部所有职工的信息 删除离职职工 按照编号删除指定的职工 修改职工信息 按照编号修改职工个人信息
  • python笔记-排序函数

    List排序 sort val list 1 7 3 9 5 6 val list sort sort 没有返回值 在原列表上排序 val list sort reverse True 逆序 print val list 使用sort 方法
  • IDEA启动tomcat控制台中文乱码问题

    IntelliJ IDEA是很多程序员必备且在业界被公认为最好的Java开发工具 有很多小伙伴在安装完IDEA并且tomcat之后 启动tomcat会出现控制台中文乱码问题 如下图所示 具体解决步骤 一 修改当前 Web 项目 Tomcat
  • 从用户页面获取作品列表

    最近web端更新比较频繁 所以搞了很多方案来应对更新问题 本文内容是其中一种方案 从用户主页的HTML响应内容中抽取user信息和作品列表数据 下图中出现的内容都是在html名为RENDER DATA的script标签中 以urlencod
  • spring与loc

    loc 是控制反转 是一个概念 当前比较流行的实现方式有两种 一种是依赖查找 第二就是依赖注入 依赖注入是目前最优秀的解耦方式 第一个小程序 所需的jar包 spring beans 4 2jar spring context 4 2 ja
  • 5折交叉验证_交叉验证:评估模型表现

    注明 本文章所有代码均来自scikit learn官方网站 在实际情况中 如果一个模型要上线 数据分析员需要反复调试模型 以防止模型仅在已知数据集的表现较好 在未知数据集上的表现较差 即要确保模型的泛化能力 它指机器学习对新鲜样本的适应能力
  • 重写或替换jar中的类或方法两种方式

    上一篇 还没毕业 我就进了HR的黑名单 目录 序言 重写jar的两种方式 第一种 第二种 序言 在某些特殊场景下 我们需要修改 jar 包中的某些类和方法 jar 我们没有修改权限 那么怎么重写里面的类和方法呢 本文教你两种常用的方法 分享
  • TortoiseGit SSH拉取GitLab代码

    ING 前述 Git获取远端代码的方式主要有两种https和SSH 这两种方式的主要区别在于 1 https url克隆会比较方便 复制https url然后到git Bash里面直接用clone命令克隆到本地就好了 但是每次fetch和p
  • 黑猫带你学eMMC协议第19篇:eMMC RPMB区域详解(重放保护内存块)

    1 前言 1 1 声明 本文依据eMMC JEDEC5 1 网络资料及个人工作经验整理而成 如有错误请留言 本文结合eMMC JEDEC5 1协议手册查看效果更佳 文章为个人辛苦整理 付费内容 禁止私自转载 1 2 内容提要 本文大约一万一
  • 2. Redis持久化、主从哨兵架构详解

    分布式缓存技术Redis 1 Redis持久化 1 1 RDB快照 snapshot 1 1 1 bgsave的写时复制 COW 机制 1 2 AOF append only file 1 2 1 AOF重写 1 3 Redis 4 0 混
  • flea-frame-db使用之基于EntityManager实现JPA分表的数据库操作【旧】

    基于EntityManager实现JPA分表的数据库操作 引言 1 EntityManager持久化操作 2 分表规则定义 3 分表操作实现 4 自测 4 1 新增数据 4 2 查询数据 4 3 更新数据 4 4 删除数据 更新 引言 本文
  • 在不影响线上服务情况下,删除大表数据表

    在不影响线上数据库服务情况下 如何删除数据库中的大表 分析 数据库中表涉及到db和os两个层面 1 db层面删表涉及到table cache的全局唯一锁 一旦数据表过大 会长时间占用全局为一锁 导致db卡死 2 os层面涉及到数据表物理文件
  • 伤腰的Python爬虫案例,零基础必备实战教程。

    前言 今天带大家采集一个二次元图片网站 里面漂亮的小姐姐层出不穷 图片的数据量也是比较大的 来一睹为快吧 开发环境介绍 python 3 6 pycharm requests parsel os 爬虫案例数据采集一般步骤 找数据对应的链接地
  • conan的学习与使用

    conan学习与使用 资源 官方地址 C C Open Source Package Manager conan io 重要概念 什么是包管理工具 包管理工具的主要作用是管理第三方依赖 也可以看成一个 轮子 工厂 每个人都可以上传自己造的
  • verdi显示数据

    在波形数据上点右键 2 s complement 就是大家计算机课上学的 补码 1 s complement 是课上讲的 反码 signed magnitude 最高位是符号位 0 正数 1 负数 低位是绝对值 另外 ncverilog v
  • FFmpeg命令行工具学习(五):FFmpeg 调整音视频播放速度

    转自 https www cnblogs com renhui p 10709074 html FFmpeg对音频 视频播放速度的调整的原理不一样 下面简单的说一下各自的原理及实现方式 一 调整视频速率 调整视频速率的原理为 修改视频的pt
  • QT之实现简陋聊天

    相关知识 QT 数据库 TCP IP Socket 1 登陆界面 包含登陆和注册两种功能 思路如下 难点 建立服务器和数据库 数据库保存数据 服务器与数据库产生联系 解决 数据库与服务器放在同一个类中 登陆和注册时 客户端与服务端连接 传输
  • 数据结构与算法(Java描述)-19、哈夫曼树、哈夫曼编码算法

    一 哈夫曼树的基本概念 在一棵二叉树中 定义从A结点到B结点所经过的分支序列叫做从A结点到B结点的路径 从A结点到B结点所经过的分支个数叫做从A结点到B结点的路径长度 从二叉树的根结点到二叉树中所有叶结点的路径长度之和称作该二叉树的路径长度
  • ctfshow 网络迷踪做题记录(1)

    ctfshow 网络迷踪做题记录 1 新手上路 找桥的名字 附件为一张海边图片 百度识图为蜈支洲岛 得到地点名 但还需要具体桥的名字 再用搜索引擎搜索关键字 就可以看到结果中的 情人桥 初学乍练 题目描述 提交这架飞机的目的地 附件图片为一
  • 十分钟让你搞懂会用Spring Retry

    一 项目的配置 为了启用 Spring Retry 的支持 首先要在pom xml 文件中添加以下依赖项

随机推荐

  • 良许Linux

    一个系统管理员可能会同时管理着多台服务器 这些服务器也许会放在不同的地方 要亲自一台一台的去访问来管理它们显然不是最好的方法 通过远程控制的方法应该是最有效的 Linux系统的远程管理工具大概有几种 telnet ssh vnc等 其中ss
  • motionface respeak新的aigc视频与音频对口型数字人

    在当今的数字化时代 人工智能 AI 正在逐渐渗透到我们生活的方方面面 其中 AI技术在视频制作和处理领域的应用也日益广泛 本文将探讨如何利用AI技术实现视频中人脸与音频同步对口型的方法 旨在进一步丰富视频制作的效果和表现形式 数字人一件对口
  • 由于无法验证发布者,Windows已经阻止此软件

    Windows系统都很注重系统的安全性 在提高安全性的同时 也给我们某些应用带来不便 比如在日常工作中经常会到某些网站上进行登录 需要安装该站点的ActiveX控件 否则无法正常加载 这时可能会弹出 由于无法验证发行者 所以WINDOWS已
  • matlab中由离散点生成云图,[转载]在matlab中由离散点生成云图

    首先 有离散点的数据如下 x 376 82 377 56 379 74 421 20 419 41 417 82 418 80 458 86 457 72 459 55 461 64 500 27 501 51 499 48 498 02
  • U盾的工作原理

    你的数字证书有一对 一份在U盾里的私钥 一份在银行的公钥 其实两份银行都有 U盾的原理很类似于双向认证的TLS SSL 或者其它用到RSA的双向证书验证手段 以下步骤可能和U盾实际执行的有所区别 但本质相同 银行先给你一个 冲击 它包含了随
  • No module named ‘cv2‘ 解决办法 (No module named ‘numpy‘ 等所有报错均可解决)

    更多视觉额自动驾驶项目请见 自动驾驶项目 实在不行可以私信我解决 0 常规解决方案 1 当出现No module named cv2 解决方案 pip install opencv python i https pypi tuna tsin
  • 等价类划分法设计测试用例

    等价类划分法 一 方法简介 1 定义 是把所有可能输入的数据 即程序的输入域划分策划国内若干部分 子集 然后从每一个子集中选取少数具有代表性的数据作为测试用例 方法是一种重要的 常用的黑盒测试用例设计方法 2 划分等价类 等价类是指某个输入
  • C++ 使用类成员函数的地址

    include
  • Linux基础笔记3

    操作系统基本认识 Linux 是什么 百度百科是这样定义 Linux Linux 全称GNU Linux 是一种免费使用和自由传播的类UNIX操作系统 其内核由林纳斯 本纳第克特 托瓦兹于1991年10月5日首次发布 它主要受到Minix和
  • 栈的实现(C语言版)

    大家好 这篇我们继续讲解数据结构里的栈 文章目录 栈的概念 栈的实现 栈的结构 栈的初始化 栈的销毁 栈是否为空 删除函数 取栈顶的数据 栈里数据的个数 插入函数 栈的概念 栈 一种特殊的线性表 其只允许在固定的一端进行插入和删除元素操作
  • js+canvas仿微信《弹一弹》小游戏

    前言 半年前用js和canvas仿了热血传奇网游 地址 基本功能写完之后 剩下的都是堆数据 堆时间才能完成的任务了 没什么新鲜感 因此进度极慢 这次看到微信 弹一弹 比较火 因为涉及到物理引擎 为了真实 于是动手试了一下 一共用了10个小时
  • 软工导论知识框架(二)结构化的需求分析

    本章节涉及很多重要图表的制作 如ER图 数据流图 状态转换图 数据字典的书写等 对初学者来说比较生僻 本贴只介绍基础的轮廓 后面会有单独的帖子详解各图表如何绘制 一 结构化的软件开发方法 结构化的分析 设计 实现 二 需求分析的重要性 1
  • QT5 出现一些问题的解决 办法

    版本 Qt Creator 5 4 0 mingw QT编写串口助手 1 extra qualification Widget on member ConvertHexChar fpermissive error extra qualifi
  • Mybatis使用拦截器实现数据权限

    1 自定义注解 Documented Target ElementType METHOD Retention RetentionPolicy RUNTIME public interface Permission Documented和 D
  • set_input_delay

    set input delay如何约束 3 FPGA时序约束理论篇之IO约束 数字IC剑指offer 建立时间 setup time 和保持时间 hold time 详析 建立时间和保持时间 setup time 和 hold time 数
  • 页面上下、左右滑动(selenium+python:Web自动化)

    1 上下滑动 滑动至页面底部 这个是固定写法 可以直接用 js1 window scrollTo 0 document body scrollHeight self driver execute script js1 滑动至页面顶部 这个也
  • SAS EM(六)时间序列理论

    SAS EM 六 时间序列理论 大家以前会听说过AR模型 MA模型 ARMA模型 ARIMA模型 这些到底是什么呢 今天来简易讲解一下 顺便用sas实操一下 由于本文是基于自己学习的归纳总结 若有讲得不对的地方 也希望读者指出 会及时修改
  • java根据模板生成world文件

    首先找一个world文件模板修改一下 类似如下图修改 修改完之后保存文件先保存xml文件之后修改ftl后缀名 保存成xml之后 有的时候改的有问题 需要使用文本查看器修改 手动的修改完整为 gongchenmingchen 这样的 所以需要
  • 虚拟机教程(一) 启用win10自带虚拟机

    由于本人电脑是win10 故尝试以下win10 自带的Hyper V虚拟机 特写教程如下 刚刚都写好了 不知道什么原因保存失败 刷新后整个都没了 草稿箱都找不到 重新写 一切从简 第一步 打开控制面板 gt 程序和功能 gt 启用windo
  • 浅谈Node中的模块化

    关于这篇文章早在去年年初的时候我就想写一片关于模块化的文章 但是推到现在才来完成也有很多好处 巩固之前对Node的理解 毕竟在我目前的项目中还没有一款项目是用到了Node开发 所以导致我对Node的一些基本知识已经忘记 一 什么是模块化 现