Node.js小白开路(一)-- 全局变量篇
全局内容是有点类似于我们在浏览器编程的时候的window对象的,当时在node之中虽然我们编写的变量会自动的给出上下文环境(模块),但是全局变量的存在还是大大的帮助了我们编程时候的便捷性。我们可以在任意的模块之中使用全局环境下面定义的内容。
global其实就相当于在web编写线面的window内容。是为nodeJS中的全局变量内容。其中存储的内容包括,console的全局实例,process信息内容,定时函数内容,Buffer对象内容等,当然还有一些特殊信息的变量。下面我们一一来说明。
## 首先我们来看一看其中连个特殊的全局变量,__dirname和__filename。我们先来上一段代码吧。
-----------------mod.js-----------------
console.log('mod.js的filename:'+ __filename);
console.log('mod.js的dirname:'+ __dirname); -----------------main.js-----------------
require('./mod.js');
当我们运行main.js的时候nodeJS会自动的先将mod.js的内容运行一遍,然后我们就可以在控制台看到打印出来的信息了。
当然两者之间还是有些差别的,__dirname 的值其实相当于path.dirname(__filename),__filename展示的是文件的局对路径包括文件名称。而__dirname展示的是文件所在的文件夹的路径信息。
## 接下来我们聊一聊require,module,exports的部分。
相信只要稍写过nodeJS的人都知道这3个次。require方法来请求模块,module表示当前文件模块本身,exports内容表示的是模块对外接口部分。
require内容用于我们请求相关模块内容,当我们传入了文件的相对路径给require方法之后,我们将得到一个引入模块的对象。但是我们常常使用npm来下载项目支持的模块文件,这是我们常常只需要输入模块名称之后reqiure会自动的引入相关的内容。这是因为在工程文件之下,在node_modules文件夹之中,我们用模块名称命名的文件夹,require会一句模块名称到相应的文件夹之中找到默认的index.js文件来进行引入。当然也是可以修改名称的,只是这时我们需要运用到package.json文件来描述这一模块内容的信息,这样我们可以指定进入模块的文件。当然require在引入了某一个文件以此之后再次引入的时候其实是无需再次读取文件的,因为require之中有缓存机制内容,之后再次请求的时候其实是直接从对应的内存之中获取。在0.3的版本之后require之中添加了require.cache对象以键值对的形式存储,当然我们能通过键值key的部分来进行缓存内容的删除,那么下一次再加载的时候则模块会重新加载。我们;爱看一段代码吧:
var ser = require('./src/h_server.js');
var buf = require('./src/h_buffer.js');
console.log(require.cache); //引入当前的两个外界模块,打印相关的require.cache内容
结果如下:
这里我截取的是其中一段内容,一个对象属性,可以看到,齐以文件路径内容为变量名称,以module内容座位属性来进行存储,所以我们要删除档当前对象中的内容的情况只需要通过文件路径查找到module对象并删除就好。
P.S.:包管理器内容(nodeJS文档中与module模块文档下的附加内容)
这里详细说一下包引入与管理,当我们在某一文档下创建自己的node工程的时候,我们常常需要外部引入许多的模块内容,这是我们通过NPM来下载模块的时候回发现工程目录之下会多出一个文件夹名称为node_module,并为每一个下载的外链模块有一个单独的文件夹内容。这时候我们可以通过模块名称来直接引用相关的模块内容,这是因为包管理器,当我们内容引入的时候会遵从一定的规则内容,这里我引用一张官网的总结内容。
从 Y 路径的模块 require(X)
1. 如果 X 是一个核心模块,
a. 返回核心模块
b. 结束
2. 如果 X 是以 '/' 开头
a. 设 Y 为文件系统根目录
3. 如果 X 是以 './' 或 '/' 或 '../' 开头
a. 加载文件(Y + X)
b. 加载目录(Y + X)
4. 加载Node模块(X, dirname(Y))
5. 抛出 "未找到" 加载文件(X)
1. 如果 X 是一个文件,加载 X 作为 JavaScript 文本。结束
2. 如果 X.js 是一个文件,加载 X.js 作为 JavaScript 文本。结束
3. 如果 X.json 是一个文件,解析 X.json 成一个 JavaScript 对象。结束
4. 如果 X.node 是一个文件,加载 X.node 作为二进制插件。结束 加载索引(X)
1. 如果 X/index.js 是一个文件,加载 X/index.js 作为 JavaScript 文本。结束
3. 如果 X/index.json 是一个文件,解析 X/index.json 成一个 JavaScript 对象。结束
4. 如果 X/index.node 是一个文件,加载 X/index.node 作为二进制插件。结束 加载目录(X)
1. 如果 X/package.json 是一个文件,
a. 解析 X/package.json,查找 "main" 字段
b. let M = X + (json main 字段)
c. 加载文件(M)
d. 加载索引(M)
2. 加载索引(X) 加载Node模块(X, START)
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
a. 加载文件(DIR/X)
b. 加载目录(DIR/X) NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I >= 0,
a. if PARTS[I] = "node_modules" CONTINUE
b. DIR = path join(PARTS[0 .. I] + "node_modules")
c. DIRS = DIRS + DIR
d. let I = I - 1
5. return DIRS
当然,在我们加载模块的时候,当两个相同的模块放在不一样的位置的时候加载的时候可能会重复加载并存储两个分加载之后的模块对象,因为齐路径的不相同,所以可能nodeJS无法进行比对。
当让在我们引入的模块的时候有的时候会遇到循环引入的情况。这时node很可能会返回一个没有执行完成的模块对象内容来。
## module内容为模块,在我们编写每一个JS文件的时候,node都认为他是一个模块,而module对象是代表当前编写的这一模块的信息。
module模块是nodeJS的重要的组成部分,之前戳到nodeJS是以COMMONJS的规则来进行编写的,而module着可以说是组成这一规则的核心内容了。
由于NODEJS会将每一个文件看成一个模块,所以通过node来进入的模块实际上是我们的主体逻辑模块内容,所以我们又是需要判别当前运行模块是否为主模块,这时我们可以通过require.main属性来确认。module模块之中会存储文件入口路径,我们可以通过module中的filename属性来获取,其值与在模块之中调用__filename获取的值多数情况之下是相同的。当然我们如果想要获取住模块的入口路径我们也可以通过,require.main.filename来获取,由此可见require中的main属性存储的实际上是组模块对象。
下面说一下模块的包管理器,其原理实际上是将模块放入到一个自执行函数之中,这样的好处显而易见了,首先是可以隔绝当前的模块与全局环境,以免全局环境被污染,同时这样为模块确定独立的上下文使得每一个模块之间的上下文不相互干扰,当某一模块之中与另一模块之中存在相同名称的命名的时候不会出现冲突的情况,nodeJS的实现方式如下:
(function(exports, require, module, __filename, __dirname) {
// 模块的代码实际上在这里
});
接下来我们来看一看module对象之中的某些属性内容:
-- children:这个属性展示的是一个列表内容,其中存储的是当前模块引用的模块对象。
-- parent:这个属性则存储的是引用当前模块对象的模块对象。
-- loaded:这个属性表明的是当前的模块是否已经加载完成了。
-- path:这个属性存储的是模块的搜索路径。
-- filename:这个属性内容存储的是模块的完全解析后的文件名。
-- id: 模块的标识符。 通常是完全解析后的文件名。
-- exports:这个属性是重中之重,属性中存储的是当前模块的公用方法内容,当使用require来引入模块的时候,实际上就是通过这属性来确立的,exports可以理解为模块暴露在大众视线下面的接口。当然我们也能说得更为的概念化一点,官方文档是如是说的—— exports变量是在模块的文件级别作用域内有效的,它在模块被执行前被赋予 module.exports 的值。
## exports属性是一个文件级别作用域有效的属性,之前在module之中有提到这一属性,但是module.exports这一属性和单独的exports还是有些不相同的所以才会将这一属性单独拿出来说事。exports属性只要是编写的朋友都知道,通过它其实也是可以对module.exports这一属性进行相关的赋值的。例如,当我们对某一文件下面使用exports对象属性赋予a属性,并对a赋值为‘1’,如展示
exports.a = '1';
这时候nodeJS会自动的将其内容复制给module.exports属性之中。当module.exports指向的对象没有变而只是变化对象内容的时候,则exports指向的对象其实也是会变的。代码如下:
console.log(module.exports); //展示最初的module.exports属性中的内容
console.log('_______________________________'); //改变exports的值,看module.exports内容会如何变化。
exports.main = 'main.js';
console.log('exports:');
console.dir(exports);
console.log('module.exports:');
console.dir(module.exports);
console.log('_______________________________'); //改变module.exports的值看exports会如何变化
module.exports.checkData = 'checkData';
console.log('exports:');
console.dir(exports);
console.log('module.exports:');
console.dir(module.exports);
console.log('_______________________________'); //改变module.exports指向的对象,看exports的变化。
module.exports = {
main:'afterChange'
}
console.log('exports:');
console.dir(exports);
console.log('module.exports:');
console.dir(module.exports);
console.log('_______________________________'); //再次改变exports的值,看module.exports怎样变化。
exports.checkAgain = 'checkAgain';
console.log('exports:');
console.dir(exports);
console.log('module.exports:');
console.dir(module.exports);
console.log('_______________________________');
相应结果内容:
由上面可以知道,在我们编写模块的时候初始情况下exports和module.exports是指向同一个对象的,所以exports在改变的时候module.exports也会跟着改变,而当module.exports改变其指向的obj之后我们可以发现其之间的变化不相关了。所以我们其实可以这样理解,当初始化的是时候的全局的exports属性和module.exports是指向同一个空的obj的。而当改变了其中一个属性的指向的时候则两个变量将不会再有任何关系。
##定时函数内容的学习。
我们在编写JS的时候经常会使用到定时函数等内容,来延时执行或者是循环执行某一段逻辑内容当然nodeJS之中也是有相对应的函数的,其中主要的有3个形式的函数内容。分别是setInterval,setTimeout,setImmediate。前两个函数内容就不用多说了,写过JS的都知道,第三个函数的作用是当前事件循环结束的时候立马执行(事件循环之后会有说)。
下面我们来了解一下timeout类,这是nodeJS中的一个定时器对象,setTimeout和setInterval对象执行的时候其返回的内容在nodeJS中是一个定时器对象。当定时器对象是活动的状态的时候,则事件循环就会将其添加到的档次循环待执行列表之中。当然nodeJS为我们添加了两个设置timeout对象活动状态的函数,ref()使得定时器对象处于活动状态,unref()使得当前定时器函数处于非活动状态。
Node.js小白开路(一)-- 全局变量篇的更多相关文章
- Node.js小白开路(一)-- console篇
在所有内容的学习之中我们经常首先要接受到的常常很大一部分为命令行或是工具的内容展示,console内容为node.js在命令行中答应数据内容的一个途径. Console是nodejs中的元老级模块了. ...
- Node.js小白开路(一)-- events篇
时间或许可以说是以JS来理解世界的基础,针对于某一个情况对象会做出何种反应,反应之后会做出何种处理,以及这一事件衍生出来了哪一些变化. 大多数 Node.js 核心 API 都采用惯用的异步事件驱动架 ...
- Node.js小白开路(一)-- Buffer篇
Buffer是nodeJS中的二进制缓存操作模块内容.先来看一段简短的代码. // 创建一个长度为 10.且用 0 填充的 Buffer. const buf1 = Buffer.alloc(10); ...
- Node.js小白开路(一)-- fs篇
文件操作在我们的日常功能模块之中是十分的常见的内容,nodeJS也不例外的为我们提供了之一操作内容,当时在我们了解文件操作的之前我们先来了解一下链接. 连接可以理解成为一个纸箱相关文件内容的地址,其主 ...
- Node.js最新技术栈之Promise篇
前言 大家好,我是桑世龙,github和cnodejs上的i5ting,目前在天津创业,公司目前使用技术主要是nodejs,算所谓的MEAN(mongodb + express + angular + ...
- Node.js 自学之旅(初稿篇)
学习基础,JQuery 原生JS有一定基础,有自己一定技术认知(ps:原型链依然迷糊中.闭包6不起来!哎!) 当然最好有语言基础,C#,java,PHP等等.. 最初学习这个东西的原因很简单,在园子里 ...
- Node.js之路【第一篇】初识Node.js
什么是Node.js 1.Node.js就是运行在服务端的JavaScrip. 2.Node.js是一个基于Chrome JavaScrip运行时简历的一个平台. 3.Node.js是一个非阻塞I/O ...
- 深入理解node.js异步编程:基础篇
###[本文是基础内容,大神请绕道,才疏学浅,难免纰漏,请各位轻喷] ##1. 概述 目前开源社区最火热的技术当属Node.js莫属了,作为使用Javascript为主要开发语言的服务器端编程技术和平 ...
- Node.js入门教程 第五篇 (Express框架)
Express框架 Express是适用于Node.js web的框架,提供了大量实用功能,例如路由功能及http功能. Express 框架核心特性: 可以设置中间件来响应 HTTP 请求. 定义了 ...
随机推荐
- Notice公告
把网页放大到125%食用效果更佳 考试题目的密码是ftp的密码 博猪很菜,菜得抠脚,如果写的有什么问题可以在评论区指出:-) 博猪qq:1755833514
- Shell下syntax error: operand expected (error token is “-”)
在这个监控实时网口速率的脚本中,第21,22行存在错误: #!/bin/bash #Modified by lifei4@datangmobile.cn echo ===DTmobile NetSpe ...
- OVN实战---《The OVN Gateway Router》翻译
Overview 在本文中我将在前文的基础上添加一个OVN gateway router.gateway router将使得lab network能访问我们的overlay network The l ...
- 【MonogDB】The description of index(二) Embedded and document Index
In this blog, we will talk about another the index which was called "The embedded ". First ...
- Android 屏幕切换动画
public void overridePendingTransition (int enterAnim, int exitAnim) Call immediately after one of th ...
- mysql 练习题(Day44)
init.sql文件内容 /* 数据导入: Navicat Premium Data Transfer Source Server : localhost Source Server Type : M ...
- 关于WinIO.DLL的键盘输入模拟
关于WinIO.DLL的键盘输入模拟 最近在找键盘模拟的方式,最后在网上找到了一个WinIO.DLL的IO键盘模拟按键的方式.但是居然那个方法是有问题的.我造了全局的hook监视键盘信息,发现它只是有 ...
- python报错 TypeError: string indices must be integers
所以在读取字典的时候,最好先判断类型,然后再查看它是否已经有这样的属性: type(mydict) == type({}) #检查不是字典 如果是字典,再看看有没有这样的属性: ...
- JavaScript判断对象 是什么类型的.
// 这种方法不起作用 if (x == undefined) { // 作某些操作 } // 这个方法同样不起作用- if (typeof(x) == undefined) { // 作某些 ...
- 2018年Java面试题搜集
2018年Java面试题搜集 一.Servlet执行流程(浏览器访问servlet的过程容器) 客户端发起http请求,web服务器将请求发送到servlet容器,servlet容器解析url并根据w ...