NodeJS 运行环境包含 CommonJS 模块规范、global 全局对象、process 当前进程

CommonJS 模块规范

理解 CommonJS 模块前先来看一个简单的例子:

创建一个 run.js 文件

console.log("This is a test");

之后通过 NodeJS 的 debug 调试工具可以看到


NodeJS 自动给我们创建了一个函数,将我们的代码放置在函数内部,其中 exports 代表我们需要向外暴露的模块或接口;require 表示需要依赖别的模块时调用的 function;module 代表模块本身。

由此我们可以总结出 CommonJS 的几条特性:

1、每个文件都是一个模块,有自己的作用域(每个文件有且只能有一个模块,因为 NodeJS 将其代码放在函数体内,所有都有其自己的作用域)2、在模块内部 module 变量代表模块本身3、module.exports 属性代表模块对外的接口

我们来看一个例子:

创建一个 cusmod.js 文件

console.log("this is a module");
// 定义一个变量
let testVar = 100;
// 定义一个函数
function test(){console.log(testVar);
};
// 将变量与方法暴露出去以便别的文件引用
module.exports.testVar = testVar;
module.exports.test = test;

既然变量与方法已经暴露出去,那么一定会在另一个文件中接收它,那么就有引出了 require 函数,我们先来看一下 require 函数的规则:

1、/ 表示绝对路径,./ 表示相对于当前文件的路径
2、支持 js、json、node 拓展名,不写依次尝试(如果引用的路径不写扩展名,则会依次查找,如果找不到就会报错)
3、不写路径则认为是 node 自带的模块或者是各级 node_modules 内的第三方模块

现在我们新建一个 require.js 去引入 cusmod.js 文件

// 使用 require 引入 cusmod.js 文件(不写拓展名则会依次查找)
let mod = require("./cusmod);
// 打印 cusmod.js 中定义的 testVar
console.log(mod.testVar)
// 调用 cusmod.js  中定义的 test 方法
mod.test();

我们可以看到其输出结果为:


此处不仅将我们暴露的东西打印出来了,还将 cusmod.js 中定义的 console 也打印出来了,由此可以看出在 cusmod.js 中一些没有被暴露出的输出也会被打印出来,所以对于一些不想让用户看见或者不想暴露出来的东西,我们最好将其封装到方法中,等待调用时再获取。

让我们再来看看另一个例子:

创建一个 cache.js 文件

// 引入两次 cusmod.js 文件
require("./cusmod);
require("./cusmod);

看一看输出的结果:

我们可以看到虽然引入了两次 cusmod.js 文件,但是只调用了一次,这就引出了 require 的第一条特性即 module 被加载的时候执行,加载后缓存。

我们再来看看 require 的另一个特性

还是先看一个例子:

创建一个 modA.js 文件

module.exports.test = "A";
let modB = require("./modB");
console.log("modA"+modB.test);
module.exports.test = "AA";

再创建一个 modB.js 文件

module.exports.test = "B";
let modB = require("./modA");
console.log("modB"+modA.test);
module.exports.test = "BB";

最后再创建一个 main.js 文件

let modA = require("./modA");
let modB = require("./modB");
console.log(modA.test);
console.log(modA.test);

最后的输出结果如图所示:


我们根据结果进行分析

首先,main.js 中调用了 modA.js 文件,当 modA.js 执行到 let modB = require("./modB") 这句时会去调用 modB.js 文件,当 modB.js 执行到 let modB = require("./modA") 这句时就形成了对 modA.js 的循环加载,此时当 modB.js 执行到 console.log(“modB”+modA.test)这句时只会输出 modA.js 中已经执行的部分,所以打印出 “modB:A”;当 modB.js 执行完之后又会回到 modA.js 中,而此时 modB.js 中 test 已经变成 BB ,所以输出的结果为 “modA:BB”;这样 main.js 中的第一句就执行完毕了,而由于 “module 被加载的时候执行,加载后缓存”的特性,第二句将不会执行。

综上实例,我们可以得出 require 的两条特性:

1、module 被加载的时候执行,加载后缓存
2、一旦出现某个模块被循环加载,就只输出已经执行的部分,还未执行的部分不会输出

最后,我们再来看一个问题:

还是先看这张图

NodeJS 给我们创建的函数的参数中有一个 exports,另一个参数 module 是一个对象其中也包含这一个 exports,那么它们两个有什么区别呢?

实际上,NodeJS 在创建函数之前有这么一句话"const exports = module.exports",将 module.exports 赋值给了 exports,也就是说它们在某种意义上是相等的,但是有一种情况只可以使用 module.exports 而不能使用 exports,让我们来看下面这个例子:

exps.js

exports.test = 100;

main.js

const mod = require("./exps.js");
console.log(mod.test);

其输出结果为:


这是显而易见的。

但是我们将其改变一下,如下所示:

exps.js

exports = {a : 2,b : 3,test : 100
}

expamain.js 保持不变其输出的结果就会变成:


由此可见,在使用 exports 时,我们可以向其中添加属性,此时 exports 与 module.exports 是一样的,但是如果需要赋值为对象时,我们只能使用 module.exports ,因为使用 exports 会改变 exports 的指向使其不再指向 module.exports 而是指向新赋值的对象,从而导致 exports 不再与 module.exports 相等

global

global 与浏览器中的 window 一样,在浏览器中我们将一些常用的属性放入 window 中以方便使用,而在服务器中则将常用的属性放入了 global 中。

在 global 中的一些属性:

CommonJS

Buffer、process、console

timer

这些属性会在后面做详细了解,我们现在只来看一个例子初步理解一下 global

global.js

const testVar = 1000;

main.js

const mod = require("./global");
console.log(testVar);

此时的输出结果为:

可以看出 testVar 是未定义的。

我们稍微改变一下:

global.js

slobal.testVar = 2000;

main.js

const mod = require("./global");
console.log(testVar);

这次的结果为:

这次结果输出来了,没有报错,说明 testVar 已经添加到全局了

process

process 顾名思义就是进程的意思,它其中包含了许多跟进程执行相关的事件和方法,先来看几个常用的比较重要的对象:

argv – 表示启动 process 时所有的参数,返回的是一个数组

我们举个例子来看一下 argv 所返回的东西

argv.js

const {argv} = process;   // ES6 语法引入 process 中的 argv 对象
// 循环遍历 argv 返回的数组
argv.forEach((item) => {console.log(item);
});

其输出结果为:

显而易见,输出的第一个是 NodeJS 所在的位置,第二个当前执行的文件所在的位置。

除此之外,我们还可以添加参数,如图所示:

其输出的结果就会连参数也输出出来。

execArgv – 获取调用 node 所传入的一些特殊参数

修改一下 argv.js

const {execArgv} = process;
console.log(execArgv);

其输出结果为:


可以看出 node 命令后传入的参数被打印出了。

execPath – 获取 node 所在的目录

再来修改一下 argv.js

const {execPath} = process;
console.log(execPath);

其输出结果为:


可以看出其打印的结果就是 NodeJS 所在的目录,其实也就是 argv 返回的数组的第一个。

cwd – cwd 是一个方法,获取当前项目所在的路径

再来修改一下 argv.js

const {cwd} = process;
console.log(cwd());

其输出结果为:

env – 获取一些与环境相关的信息

env.js

const {env} = process;
console.log(env);

其输出结果为:


这就是获取的一些与环境有关的信息。

timer – 包括一些延时调用的命令,setImmediate、setTimeout 以及 process.nextTick

首先来看个例子:

timer.js

setImmediate(() => {console.log("setImmediate");
});setTimeout(() => {console.log("setTimeout");
},0);process.nextTick(() => {console.log("nextTick");
});

其输出结果为:


我们可以看出 process.nextTick 最先输出,setImmediate 最后输出,setTimeout 在它们中间输出。

事实上,setImmediate 是延时调用,它会在下一个事件队列开始时去执行,相当于一个异步,而 process.nextTick 是在当前队列中的东西都执行完后再执行它,因此它比 setImmediate 执行的早,setTimeout 的执行时间则是位于它们中间。

你可能认为 setImmediate 与 process.nextTick 没有什么区别,但事实并非如此,process.nextTick 是在当前事件队列的最后执行,可如果在其中循环调用 process.nextTick 就可能导致程序不能继续向后执行,一直执行 process.nextTick,因此在大部分情况下,我们都使用 setImmediate 。

NodeJS 运行环境相关推荐

  1. Ubuntu上sublime配置nodejs运行环境

    Ubuntu上sublime配置nodejs运行环境 如果阅读无障碍的话可以直接查看https://packagecontrol.io/packages/Nodejs上面说的很详细 如果不想看的话, ...

  2. 安装NodeJs运行环境

    关于大名鼎鼎的Nodejs是什么就不用再介绍了,他的牛逼之处数都数不完--让javascript称霸全宇宙.将一个只用于前端的编程语言同时可以制霸前后端.让致力于前端开发的小哥又多了一项事业新增了一门 ...

  3. Linux上的node站点之centos配置nodejs运行环境笔记

    centos配置nodejs运行环境 原来的项目放在windowsserver上了,现在换个系统要重新配置下. 先看看是不是安装python rpm -qa|grep python 一般租的云服务器会 ...

  4. nodejs运行环境配置并使用puppeteer实现后台截图

    本文目的 不知道小伙伴们有没有遇到过后台截图这样的需求,今天我将自己的经验总结出来分享给大家. 在经过前期的技术调研之后,确定了使用nodejs的puppeteer库实现后台截图,并通过java Ru ...

  5. 【树莓派不吃灰】基础篇④ Raspberry Pi上搭建NodeJS运行环境

    目录 1. 前言 2. 安装NodeJS环境 2.1 安装npm 2.2 安装nodejs 2.3 配置NPM国内镜像源 3. 总结 ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️ ...

  6. Win7搭建NodeJs开发环境以及HelloWorld展示—图解

    Windows 7系统下搭建NodeJs开发环境(NodeJs+WebStrom)以及Hello World!展示,大体思路如下:第一步:安装NodeJs运行环境.第二步:安装WebStrom开发工具 ...

  7. nodejs开发环境搭建

    项目场景: 提示:windows 10 环境下搭建nodejs运行环境: 这个事情对大部分人来说,可能不屑一顾.不就是安装上nodejs,然后一步步 npm install, npm run dev ...

  8. 下载nodejs的mysql安装包下载_nodejs安装包下载|nodejs(javascript运行环境) v5.3.0 最新稳定版 - 软件下载 - 绿茶软件园|33LC.com...

    nodejs(javascript运行环境)是款运行在服务器端的javascript.nodejs(javascript运行环境)使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效,Node ...

  9. NodeJS入门--环境搭建 IntelliJ IDEA

    NodeJS入门–环境搭建 IntelliJ IDEA 本人也刚开始学习NodeJS,所以以此做个笔记,欢迎大家提出意见. 1.首先 下载安装NodeJS,下载安装IntelliJ IDEA 2.接下 ...

最新文章

  1. Linux那些事儿 之 戏说USB(14)端点
  2. typeof,instanceof 和 isProtoTypeof
  3. kali工具中文手册_Kali Linux 2019.4发布了!解决Kali Linux 2019.4中文乱码问题
  4. Vupsen, Pupsen and 0 思维,凑系数
  5. 软件测试术语中英文对照(部分)
  6. 【HDU - 1518】Square (经典的dfs + 剪枝)
  7. linux mysql 5.7密码忘记_Mysql5.7.14 linux版密码忘记的找回方法
  8. 【渝粤教育】广东开放大学 操作系统原理与应用 形成性考核 (46)
  9. C# await和async
  10. mysql分表的原则_分库分表原则 总结
  11. Excel数据填充技巧
  12. python实现数据恢复软件手机版下载_知名下载软件,总算出手机版了
  13. 性能测试第七课--用户定义变量用户参数
  14. 如何用微信群、微信霸屏进行引流
  15. 实验二 SQL 语言——SELECT 查询操作(第一部分)
  16. 蓝桥杯 省赛真题寻找 2020
  17. Linux 下查询日志
  18. 【C++】有一个8层灯塔,每层的等数…
  19. 小米网抢购系统开发实践阅读心得
  20. 算法基础--《我的第一本算法书》--(算法学习一)

热门文章

  1. Vue实例生命周期函数(钩子函数)详解
  2. 毕业设计-基于协同过滤算法的旅游推荐系统
  3. mouseover和mouseout区别
  4. 我的互联网创业公司的第一笔收入磨难记
  5. Android发送图片到指定邮箱(仅客户端简单实现,不需服务端配合)
  6. 黑马旅游网-旅游分类线路分页显示(七)
  7. 电子取证之服务器取证,本人小白第一次从pc取证到服务器,这里有一套例题分享给大家,所有解析我都尽可能全面具体,希望与各位同仁一起学习。(非常推荐!)
  8. 电商运营之业务数据报告
  9. 幸福密码:与原生家庭和解后,才能直面真正的自己
  10. python turtle画表情包--不可以色色