node篇 CommonJS规范

news2024/9/9 5:30:17

文章目录

    • 1. 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
    • 2. 每个模块内部,module变量代表当前模块。
    • 3. 两种导出方式 exports 和 module.exports
    • 4. 一种引入方式 require
    • 5. 模块化的实现原理
    • 6. CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
    • 7. nodejs的全局对象是global
    • 8. CommonJS 模块的require()是同步加载模块

1. 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。

a.js

var a = 1;

b.js

console.log(a) // 会报错 a is not define

2. 每个模块内部,module变量代表当前模块。

console.log(module)可以查看该模块的module对象

在这里插入图片描述

Module {
  id: '.', // 模块唯一识别符,
  path: 'D:\\Codes\\Test', // 模块所在的文件路径
  exports: {}, // 模块的导出对象,这也是我们用module.exports导出的原因
  parent: null, // 如果该模块被其它模块引用,这里就是引用它的模块
  filename: 'D:\\Codes\\Test\\node1.js', // 模块的名称,通常是模块对应的完整路径
  loaded: false, // 模块是否已经加载完成
  children: [], // 模块里是否引入了其它模块
  paths: [
    'D:\\Codes\\Test\\node_modules',
    'D:\\Codes\\node_modules',
    'D:\\node_modules'
  ]
}

在前端开发中,一开始不存在模块化,比如一个html文件

<!DOCTYPE html>
<html lang="en">
  <head>
	<script src="./a.js"></script>
	<script src="./b.js"></script>
  </head>
</html>

a和b看似是两个js,但都被放在html,最终被浏览器整合了,形成统一代码执行环境,又称上下文。

在html中如何做到a与b独立呢?

<!DOCTYPE html>
<html lang="en">
  <head>
	<script src="./a.js" type="module"></script>
	<script src="./b.js" type="module"></script>
  </head>
</html>

那如何做到模块与模块之间通信呢,我们总不能把所有的逻辑一口气写到一个js文件里吧,自然得把需要的东西引入,把别的js文件需要的东西导出。

3. 两种导出方式 exports 和 module.exports

exports是module.exports的引用,这也是它们的区别。

module.exports === 特殊对象,这个对象可以被导出,在其它模块被引用 // true
// module.exports赋值给了exports 
exports = module.exports

如果我们对exports赋值会发生什么

// exports 被重新赋值了一个普通对象,这个普通对象不可以被导出,其它模块自然也用不了name属性了
exports = { name: 'dx' }
// 正确的使用exports的方式
exports.name = 'dx';

但用module.exports这样写完全没问题

module.exports = {
  name: "dx",
  age: 18,
};

4. 一种引入方式 require

4.1引入的内容是有缓存的,多次引入同一文件,只会执行一次
require引入就会执行,并且只会在第一次引入的时候执行,之后缓存在require.catch中,后面再引入,直接从require.catch取出对应的值,不再执行被引入模块本身

b.js代码如下

console.log('b')
require('./b.js')
require('./b.js')
require('./b.js') 
// b

当然我们也可以手动消除这种缓存机制,所有缓存的模块保存在require.cache之中

// 删除指定模块的缓存
delete require.cache[moduleName];

// 删除所有模块的缓存
Object.keys(require.cache).forEach(function(key) {
  delete require.cache[key];
})

4.2 require引入的三种写法
只有js文件引入的时候,后缀可以省略

 const b = require('./b') 

路径./开头和/开头也是有区别的
/b表示绝对路径下的b.js
./b 表示相对路径下的b.js

如果没有路径,只有一个文件名

const dx = require('dx') 

nodejs会认为有两种情况,第一种,第三方下载的node模块,第二种,node内置的模块。
如果dx是node内置的模块,那肯定没问题,能成功找到,不会报错。

  1. 如果dx是第三方下载的node模块,那么会先查看环境变量NODE_PATH的路径,如果没有
  2. 同级node_module文件夹下的dx模块,相当于./node_module/dx
  3. 如果同级文件夹没有,会找父级目录下的node_module文件夹的dx模块,相当于…/node_module/dx
  4. 父级也没有,会找父级旳父级 …/…/node_module/dx
  5. 会一直找到根目录下 C:\node_module\dx
  6. 最终根目录也没有的话,会报错,说找不到dx模块,并提示你安装这个叫dx的模块 npm i dx --save

4.3 require之后,内部的执行流程

  1. 检查 Module._cache,是否缓存之中有指定模块
  2. 如果缓存之中没有,就创建一个新的Module实例
  3. 将它保存到缓存
  4. 使用 module.load() 加载指定的模块文件,
    读取文件内容之后,使用 module.compile() 执行文件代码
  5. 如果加载/解析过程报错,就从缓存删除该模块
  6. 如果加载/解析没问题,返回该模块的 module.exports

5. 模块化的实现原理

a.js

const person = {
	name: 'dx',
	age: 18
}
console.log(person)
module.exports = person 

实际上会变成这样

// 准备module对象:
var module = {
    id: 'a.js',
    exports: {},
    ...
};
var exports = module.exports;
var load = function (module) {    
	const person = {
		name: 'dx',
		age: 18
	}
	console.log(person)
	module.exports = person 
    return module.exports;
};
var exported = load(module);
// 保存module:
save(module, exported);

6. CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。

// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  incCounter: incCounter,
};

// main.js
var mod = require('./lib');

console.log(mod.counter);   // 3
mod.incCounter();
console.log(mod.counter);   // 3

7. nodejs的全局对象是global

平时的JavaScript是三个部分 dom(Document Object Model 文档对象模型)bom(Browser Object Model 浏览器对象模型) 以及 ECMAScript组成。
而nodejs没有dom,也没有bom,所以nodejs的全局对象不是window,也没有history之类的东西。

8. CommonJS 模块的require()是同步加载模块

这句话的意思就是要求,所有的模块导出的数据都必须是同步的

错误示范

setTimeout(() => {
  module.exports = { welcome: 'Hello World' }
}, 0)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/13620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

腾讯云轻量应用服务器搭配WordPress程序使用宝塔面板一键式搭建个人博客网站

你想要拥有一个自己的网站吗&#xff0c;不在受第三方网站的约束&#xff0c;自由撰写文章帖子&#xff0c;随时随地发挥你的想象。其实搭建一个个人网站没有那么麻烦&#xff0c;完全小白用户也可以办到&#xff0c;只需要点点鼠标就可以完成&#xff0c;下面就详细介绍使用腾…

计网实验软件 Cisco Packet Tracer 8 获取并汉化

1. 注册账号 点击&#xff1a;https://skillsforall.com/course/getting-started-cisco-packet-tracer 进入 Skills for All 网站. 点击 Get Started&#xff0c;进入登录页 点击 Sign Up 注册&#xff0c;选择国家、出生年月&#xff0c;填写其他信息。 这里顺带放一下密码的…

HOOPS/QT集成指南

引言 以下部分&#xff0c;说明如何使用QtGUI工具包和HOOPS 3D应用程序框架构建应用程序。首先回顾编译/链接&#xff0c;然后讨论各个组件中的对象关系&#xff0c;然后概述正确创建和初始化对象以及启动Qt事件循环所需的编程步骤。 开发人员应该首先编译、链接和运行基本的q…

【11-导入人人generator项目并自动生成相关的文件商品子模块的调试公共模块common子模块的抽离与实现Lombok插件的安装】

一.知识回顾 【0.三高商城系统的专题专栏都帮你整理好了&#xff0c;请点击这里&#xff01;】 【1-系统架构演进过程】 【2-微服务系统架构需求】 【3-高性能、高并发、高可用的三高商城系统项目介绍】 【4-Linux云服务器上安装Docker】 【5-Docker安装部署MySQL和Redis服务】…

UDS知识整理(四):ECU复位——0x11服务

目录 一、0x11服务&#xff08;ECU复位&#xff09;简介 二、0x11服务信息格式 &#xff08;1&#xff09;请求格式 &#xff08;2&#xff09;正响应格式 &#xff08;3&#xff09;负响应格式 三、0x11服务举例 &#xff08;1&#xff09;如&#xff1a;硬件复位 &am…

戴尔PowerEdge R650服务器荣获国家级实验室5项证书

在今年的戴尔科技峰会上&#xff0c;IDC中国副总裁兼首席分析师武连峰的报告引起了广泛关注&#xff0c;他表示&#xff1a; “根据IDC对全球企业CEO调研&#xff0c;在CEO关注的重点中&#xff0c;技术依然排在第一位&#xff0c;然后是效率和增长。88%的全球CEO在2022年会维…

[附源码]java毕业设计龙虎时代健身房管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

知乎高赞:听说Rust要取代C++?

随着近几年Rust的大火&#xff0c;越来越多的人开始质疑&#xff0c;Rust势头这么猛&#xff0c;是不是要取代C?小慕认为&#xff0c;一门编程语言想要完全取代另一门编程语言是很难的&#xff0c;毕竟每一门技术都有它的专属优势和特点&#xff0c;总会在特别的地方发光发热。…

linux 不依赖xcode成功运行appium+ios自动化

一、原理 **1、【常规】**常规情况下&#xff0c;ios自动化需要mac机器&#xff0c;如果强行使用linux运行&#xff0c;过程会提示Xcodebuild Failure&#xff0c;也就是强依赖Xcode。 失败图如下&#xff1a; **2、【思路】**那有没有什么方法可以绕过xcode的限制呢&#xf…

创建SpringBoot项目的几种方式

使用 spring boot 提供的初始化器。 向导的方式&#xff0c;完成 spring boot 项目的创建&#xff1a; 使用 方便.(需要联网)就是下图这个,在pom.xml里 选择依赖,选择些单体SpringBoot需要用到的一些 Spring Web包含SpringMVC Tomcat SQL 基本的JDBC MysqlDriver Mybatis 第…

发电控制系统面临的主要安全威胁

电力行业 工控安全解决思路保障框架从电力行业对工控安全需求看&#xff0c;电力企业在主要是以合规性建设为主&#xff0c;在 2004 年原电监会 5 号令颁布开始&#xff0c;大部 分的电厂控制系统安全 建设已经按照 5 号令的要求进行了整改&#xff0c;形成“安全分区、网络专…

再手写线程池以及性能分析

文章目录前言一、为什么要用线程池线程池的作用线程池的使用场景二、线程池的构成以及相关API的实现线程池中的相关变量类型线程池的创建任务线程实现获取任务线程池的销毁线程池的使用前言 以前写的线程池文章请参考&#xff1a;线程池的简单实现 本次文章是对线程池的再次学…

使用Egg调用mysql实现增删改查接口操作

市场上数据库可视化工具很多&#xff0c;笔者更多时间使用的是 Navicat ,但是因为它是收费的&#xff0c;一些伙伴可能没发使用&#xff0c;所以笔者在这里推荐一款 工具 名为&#xff1a; DBevaer&#xff0c;它所展现出来的能力&#xff0c;与navicat 类似&#xff0c;并且还…

玩RTOS这么久,一问原子操作,蒙了~

已剪辑自: https://mp.weixin.qq.com/s/kvxcOHT-xHtMAjQqJu7Y2g [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C3f9Rrei-1668695258073)(https://res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/audio/icon_qqmusic_source6201b5.sv…

代码随想录——钥匙和房间(图论)

题目 有 N 个房间&#xff0c;开始时你位于 0 号房间。每个房间有不同的号码&#xff1a;0&#xff0c;1&#xff0c;2&#xff0c;…&#xff0c;N-1&#xff0c;并且房间里可能有一些钥匙能使你进入下一个房间。 在形式上&#xff0c;对于每个房间 i 都有一个钥匙列表 rooms[…

tft lcd spi 驱动

tft lcd spi 驱动参考驱动uc1701SPI设备树配置背光控制IO设备树配置SPI控制引脚配置参考驱动uc1701 linux-4.1.15-imx6ul/drivers/staging/fbtftSPI设备树配置 根据原理图修改对应引脚 linux-3.10/arch/arm/boot/dts/sun8iw11p1-pinctrl.dtsi 蔽掉引脚冲突功能 linux-3.10/ar…

如何注册公司网站?【注册公司网站】

公司网站是很多公司的必备品&#xff0c;哪怕公司并不依赖线上业务&#xff0c;也会有自己的公司网站。随着互联网的发展成熟&#xff0c;其实现在注册公司网站基本上都是比较简单的&#xff0c;那么如何注册公司网站呢&#xff1f;下面给大家说一说。 一、注册公司网站前准备…

英伟达发布526.98 WHQL 显卡驱动,支持RTX 4080,三款即将上线游戏

11月16日&#xff0c;英伟达发布了526.98 WHQL 新驱动&#xff0c;支持最新发布的RTX 4080显卡。 新驱动为《蜘蛛侠:迈尔斯莫拉莱斯》、《战锤40k:暗潮》和《魔兽世界&#xff1a;巨龙时代》提供支持。此外&#xff0c;还支持《怪物猎人崛起》的DLAA更新和WRC世代-国际汽联WRC…

【FFmpeg】ffmpeg+nginx-rtmp实现视频流转发

1.应用场景 目前的摄像头厂家能提供出来的视频流格式有限&#xff0c;且chrome已经禁止了对flash的支持&#xff0c;导致像硬盘录像机这种只能提供rtsp格式流地址的摄像头无法接入Web应用&#xff0c;所以不得不对视频的流地址进行分发&#xff0c;通过代码对流地址中的数据进…

数仓开发之DWD层(三)

&#xff08;附&#xff1a;由于篇幅原因&#xff0c;这里就不在展示代码了&#xff0c;直接告诉大家思路&#xff09; 目录 五&#xff1a;交易域订单预处理表 5.1 主要任务 5.2 思路分析 5.3 图解 六&#xff1a;交易域下单事务事实表 6.1 主要任务&#xff1a; 6.2 …