Node.js的学习(二)node.js 模块化
一、Node.js模块化
1、模块化概要
早期的javascript版本没有块级作用域、没有类、没有包、也没有模块,这样会带来一些问题,如复用、依赖、冲突、代码组织混乱等,随着前端的膨胀,模块化显得非常迫切。
通俗点来说:模块化就是把手机变成一个一个零件,可以拼装,哪个零件坏了可以换,就不用整个手机都需要换,就像搭积木一样
前端模块化规范如下:
常见的的JavaScript模块规范有:CommonJS、AMD、CMD、UMD、原生模块化(ES6的时候有学)
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换 的单元
JavaScript在早期的设计中就没有模块、包、类的概念,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码,我们称为模块化。
模块就是一个实现特定功能的文件,有了模块我们就可以更方便的使用别人的代码,要用什么功能就加载什么模块。
2、模块化开发的四点好处:
(1)、避免变量污染,命名冲突
(2)、提高代码复用率
(3)、提高了可维护性
(4)、方便依赖关系管理
nodejs 中根据模块的来源不同,将模块分为了3大类,分别是:
- 内置模块(内置模块是由Node.js官方提供的,例如fs、path、http等)
- 自定义模块 (用户创建的每个 .js文件,都是自定义模块)
- 第三方模块 (由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)
3、模块作用域
和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
模块作用域的好处:防止了全局变量污染的问题
4、变量作用域
(1)、在浏览器端使用var或不使用关键字定义的变量属于全局作用域,也就是可以使用window对象访问。
<script>
var a = 100; (function () {
b = 200;
})(); console.log(window.a, a);
console.log(window.b, b);
</script>
结果:
(2)、在 Node.js 中没有 window 对象
(3)、在Node.js的交互环境下,定义的变量属于global,global是类似浏览器端的window对象
(4)、在模块中(文件中)有global对象,使用关键字var,let,const定义的成员不属于global对象,仅在当前模块中有效,而不使用关键字定义的对象属于global对象。
var a=100;
b=200;
let c=300;
const d=400;
console.log(global);
console.log(global.a);
console.log(global.b);
console.log(global.c);
console.log(global.d);
终端输出:
5、CommonJS
CommonJS就是一个JavaScript模块化的规范,该规范最初是用在服务器端 NodeJS 中,前端的 webpack 也是对CommonJS原生支持的。
根据这个规范
(1)、每一个文件就是一个模块,其内部定义的变量是属于这个模块的,不会对外暴露,也就是说不会污染全局变量。
(2)、导入自定义的模块时路径需要以 ./ 或 ../ 开始,同一路径下也不能省略。
(3)、如果反复多次require模块,只加载一次。
(4)、require引入模块时,后缀名.js可以省略
(5)、每个模块文件都是一个独立的函数级作用域,在其它模块中不能直接访问
举个栗子:
m1.js 文件代码:
console.log("这是模块m1");
let a=100;
b=200;
m2.js 文件代码:
var m11=require("./m1");
console.log(a);
console.log(b);
结果:
从上面的示例可以看出a在模块2中是访问不到的,模块其实就是一个封闭的函数:
m1.js 文件的代码:
console.log("这是模块m1");
let a=100;
b=200;
//输出当前函数
console.log(arguments.callee+"");
输出结果:
(6)、每个模块中都包含如下5个对象:
exports:导出对象,默认为{}
require:导入函数,使用该函数可以实现模块的依赖
module:模块信息,用于记录当前模块的所有信息
__filename:当前模块的文件全路径,含文件名
__dirname:当前模块的文件路径,不含文件名
(7)、使用exports或module.exports对象可以将当前模块中需要导出的内容暴露出去。
m4.js 文件代码:
let a=100;
let b=()=>{
return 200;
};
exports.a=a;
exports.b=b;
m5.js 文件代码:
const m1=require("./m1");
console.log(m1);
console.log(m1.a);
console.log(m1.b());
运行结果:
(8)、导入模块内容可以结合结构语法
m6.js 文件代码:
exports.a=100;
exports.b=function(){
return 200;
};
m7.js 文件代码:
const {a,b:fun}=require("./m6");// 模块结合解构
console.log(a);
console.log(fun());
运行结果:
二、Node.js 文件系统
2.1、概要
Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。 Node 导入文件系统模块(fs)语法如下所示:
var fs = require("fs")
2.3、异步与同步
Node.js 文件系统(fs 模块)模块中的方法均有 异步和同步 版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。
异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。
建议大家是用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。
实例
创建 input.txt 文件,内容如下:
foo
创建 filereaddemo.js 文件, 代码如下:
const fs=require("fs"); //依赖内置模块fs,用于文件管理 //异步读取文件index.txt,设置读取成功时的回调函数,err表示错误信息,data表示数据
fs.readFile("index.txt",function(err,data){
if(err) throw err; // 抛出异常
console.log("异步:"+data+"");
}); console.log("---------------"); //同步读取
let data=fs.readFileSync("index.txt");
console.log("同步:"+data+"");
运行结果:
注意:异步完成时间是不确定的,一般异步完成时间最慢!!!
2.2、写入文件
创建 file.js 文件,代码如下所示:
const fs=require("fs"); // 异步写入文件
fs.writeFile("output1.txt","异步hello","utf-8",function(err){
if(!err){
console.log("异步文件写入成功!");
}
else{
throw err;
}
});
console.log("---------------"); // 同步写入文件
fs.writeFileSync("output2.txt","同步hello","utf-8");
console.log("同步文件写入成功");
运行结果:
2.3、获取文件信息
以下为通过异步模式获取文件信息的语法格式:
fs.stat(path, callback)
参数使用说明如下:
path - 文件路径。
callback - 回调函数,带有两个参数如:(err, stats), stats 是 fs.Stats 对象。
fs.stat(path)执行后,会将stats类的实例返回给其回调函数。可以通过stats类中的提供方法判断文件的相关属性。例如判断是否为文件:
创建一个 isfile 文件,代码如下:
// 判断是否为文件:
const fs=require("fs"); // 获取文件信息
fs.stat("student.txt",(err,stats)=>{
console.log("是文件吗?"+stats.isFile());
console.log("是目录吗?"+stats.isDirectory());
console.log(stats);
});
运行结果:
stats类中的方法有:
2.4、删除文件
以下为删除文件的语法格式:
fs.unlink(path, callback)
参数使用说明如下:
path - 文件路径。
callback - 回调函数,没有参数。
创建 deleteFile.js 文件,代码如下:
const fs=require("fs"); fs.unlink("output1.txt",function(err){
if(err){
throw err;
}
else{
console.log("异步删除文件成功!");
}
});
console.log("--------------------");
fs.unlinkSync("output2.txt");
console.log("同步删除文件成功!");
运行结果:
2.5、创建目录
以下为创建目录的语法格式:
fs.mkdir(path[, mode], callback)
参数使用说明如下:
path - 文件路径。
mode - 设置目录权限,默认为 0777。
callback - 回调函数,没有参数。
创建mkdirfile.js 文件,代码如下所示:
const fs=require("fs"); fs.mkdir("dir1",function(err){
if(err){
throw err;
}
else{
console.log("异步创建目录成功!");
}
});
console.log("---------------------");
fs.mkdirSync("dir2");
console.log("同步创建目录成功!");
运行结果:
2.6、读取目录
以下为读取目录的语法格式:
fs.readdir(path, callback)
参数使用说明如下:
path - 文件路径。
callback - 回调函数,回调函数带有两个参数err, files,err 为错误信息,files 为 目录下的文件数组列表。
创建 readDirectory.js 文件,代码如下:
// 读取目录
const fs=require("fs"); // 异步
fs.readdir("dir1",(err,files)=>{
if(err)
{throw err;}
else{
console.log("异步获取目录下的文件成功!");
files.forEach(file=>console.log(file));
}
});
console.log("-----------------------"); // 同步
let files=fs.readdirSync("dir2");
console.log("同步获取目录下的文件成功!");
files.forEach(file=>console.log(file));
运行结果:
2.7、删除空目录
以下为删除空目录的语法格式:
fs.rmdir(path, callback)
参数使用说明如下:
path - 文件路径。
callback - 回调函数,没有参数。
接下来我们创建 delDirectory.js 文件,代码如下所示:
var fs = require("fs"); // 异步删除
fs.rmdir("dir1",function(err){
if(err){
throw err;
}
else{
console.log("异步删除目录成功");
}
}); console.log("================================="); // 同步删除
// recursive:递归删除
fs.rmdirSync("dir2");
console.log("同步删除目录成功");
运行结果:
2.8、删除非空目录
以下为删除非空目录的语法格式:
fs.rm(path,callback);
创建一个delDirectory2.js 文件,代码如下:
var fs = require("fs"); // 异步删除非空目录
fs.rm("dir1",{recursive: true},err=>{
if (err) {
throw err;
}
console.log("异步删除非空目录成功!");
});
运行结果:
三、参数与环境变量
3.1、读取package.json文件配置参数
创立一个 config
目录并向其中增加一个 config/default.json
文件。这将是默认配置文件,并将蕴含所有默认环境变量。
获取配置的内容:
process.env['npm_package_config_xxxxxx']
在咱们的示例应用程序中它应该是这样的:
在 package.json 文件中,新添加一个 “ config ” ,然后设置一些自定义的参数:
然后新建一个config.js 文件,代码如下:
console.log(process.env.npm_package_config_foo);
请注意:要是直接运行,它的值为:undefined,如何解决?解决方法如下:
(1)在package.json文件中的 scripts中添加一行 “ start ”:node 要运行的文件名
(2)在终端哪里,输入命令:npm run start 回车,即可解决
3.2、读取自定义配置文件数据
首先创建一个 default.json 文件,代码如下:
{
"student":{
"name":"tom",
"age":"18"
}
}
先依赖模块config,命令如下:
npm i config
咱们将在咱们的应用程序中通过导入 config
和应用 get
办法拜访变量来访问它,代码如下:
const config = require("config"); console.log(config);
console.log(config.get("student.name"));
console.log(config.get("student.age"));
运行结果:
3.3、使用evn、dotenv依赖读取参数
(1)首先导入依赖:
npm i dotenv //依赖模块
(2)自定义创建 .env 文件代码如下:
USER_ID="239482"
USER_KEY="foobar"
NODE_ENV="development"
(3)自定义创建 env.js 文件代码如下:
require("dotenv").config();
console.log(process.env.USER_ID);
运行结果:
3.4、环境变量的设置与读取
3.4.1、查看当前所有可用的环境变量
命令如下:
set
3.4.2、查看某个环境变量
命令如下:
set 变量名
具体操作步骤如下:
首先在电脑上的属性 -> 高级系统设置中,新添加一个环境变量
请注意:在环境变量中添加或修改了变量,需要重启电脑!!!
运行结果如下:
3.4.3、修改环境变量
请注意:所有的在cmd命令行下对环境变量的修改只对当前窗口有效,不是永久性的修改。也就是说当关闭此cmd命令行窗口后,将不再起作用。
修改环境变量命令如下:
set 变量名=变量内容
运行结果:
请注意,此修改环境变量是指用现在的内容去覆盖以前的内容
3.4.4、修改环境变量为空
命令如下:
"set 变量名="
3.4.5、给变量追加内容
命令如下:
“set 变量名=%变量名%;变量内容”
3.4.6、修改环境变量的值并访问
命令如下:
set a=900 && node envcfg.js
运行结果如下:
Node.js的学习(二)node.js 模块化的更多相关文章
- vue.js 源代码学习笔记 ----- codegen.js
/* @flow */ import { genHandlers } from './events' import { baseWarn, pluckModuleFunction } from '.. ...
- Node.js基础学习二之POST请求
本篇介绍下 Node.js post 请求 需求: 用户登录,前端界面输入用户名和密码,点击登录请求后台验证,根据后台反馈的信息做出响应 前端: (1)使用form表单 (2)使用ajax异步请求 服 ...
- D3.js 入门学习(二) V4的改动
//d3.scan /* 新的d3.scan方法对数组进行线性扫描,并根据指定的比较函数返回至少一个元素的索引. 这个方法有点类似于d3.min和d3.max. 而d3.scan可以得到极值的索引而不 ...
- vue.js 源代码学习笔记 ----- html-parse.js
/** * Not type-checking this file because it's mostly vendor code. */ /*! * HTML Parser By John Resi ...
- vue.js 源代码学习笔记 ----- helpers.js
/* @flow */ import { parseFilters } from './parser/filter-parser' export function baseWarn (msg: str ...
- vue.js 源代码学习笔记 ----- codegenEvents.js
/* @flow */ const fnExpRE = /^\s*([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/ const simplePathRE = / ...
- vue.js 源代码学习笔记 ----- fillter-parse.js
/* @flow */ export function parseFilters (exp: string): string { let inSingle = false let inDouble = ...
- vue.js 源代码学习笔记 ----- text-parse.js
/* @flow */ import { cached } from 'shared/util' import { parseFilters } from './filter-parser' //找到 ...
- 测试驱动开发(TDD)及测试框架Mocha.js入门学习
组里马上要转变开发模式,由传统的开发模式(Developer开发,QA测试),转变为尝试TDD(Test-driven development,测试驱动开发)的开发模型.由此将不存在QA的角色,或者仅 ...
- node.js入门学习(五)--Demo模块化改造
1.node.js中模块的分类 1)node.js内置模块(核心,原生) 所有内置模块在安装node.js时就已经编译成二进制文件,可以直接加载运行(速度较快),部分内置模块,在node.exe这个进 ...
随机推荐
- C# 开发过程中常见错误记录及解决说明
1.异常了类型: 1.1.1.1 异常错误信息:An error occurred while updating the entries. See the inner exception for de ...
- MQ系列5:RocketMQ消息的发送模式
MQ系列1:消息中间件执行原理 MQ系列2:消息中间件的技术选型 MQ系列3:RocketMQ 架构分析 MQ系列4:NameServer 原理解析 在之前的篇章中,我们学习了RocketMQ的原理, ...
- HPC+时代,携手亚马逊云科技,共赴数字化升级的星辰大海!
高性能计算(HPC)和云计算曾是两个"平行世界",各自演绎着精彩,却鲜有交集. 传统上,HPC主要应用于大规模计算,如天气预报.石油勘探.药物研发等.这些任务通常借助超级计算机或计 ...
- javaee相关基础
2020-2-28 java 学习 开始学习javaee了 瞎跳着看 今日内容 web相关概念 web服务器软件:Tomcat Servlet入门学习 web概念 软件架构 C/S:客户端/服务器端 ...
- 第七十五篇:Vue兄弟组件传值
好家伙, 兄弟组件的传值用到Eventbus组件, 1.EventBus的使用步骤 ① 创建 eventBus.js 模块,并向外共享一个Vue的实例对象 ②在数据发送方, 调用bus.$emit(' ...
- LFS(Linux From Scratch)构建过程全记录(四):最后的准备
写在前面 本章将进行一系列的环境配置 目录创建 在LFS中创建文件目录 我们可以用以下的指令来创建一些基础的目录,并进行连接 mkdir -pv $LFS/{etc,var} $LFS/usr/{bi ...
- 【前端】在浏览器控制台,直接发Ajax请求
我们在日常的开发的过程中,经常需要前端测试发送请求测试一些数据.但是由于一些session,cookie的存在,我们无法在postman上创建一些会话.那么这样,我们就可以在浏览器上直接发送Ajax请 ...
- avue常用场景记录
接手的一个项目使用的是avue这个傻瓜式的专门给后端人员用的框架,文档不够友好,使用起来各种蛋疼(咱专业前端基本上不使用).为此,专门记录一下.当前avue版本2.8.12,如果要切换avue的版本, ...
- k8s上安装elasticsearch集群
官方文档地址:https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-quickstart.html yaml文件地址:https://dow ...
- Query String Query和Sumple Query String