前端攻城狮---node入门

xiaoxiao2025-10-21  18

本章节会讲解node的全局方法,模块化的原理,path模块以及fs模块。

 

什么是node.js

node.js是一个基于chrome V8 引擎的JavaScript运行时。

就是说这个node.js可以用来运行js文件,这样我们就不需要在浏览器里运行js文件,只需在node中,大大方便了我们的开发。

首先,大家就需要去安装好node,配置好环境变量,那么我们就可以开始学习node之旅。

node的中文官网 http://nodejs.cn/api/ 

基本node全局变量

我们先来讲解node的全局变量,当然我们不可能全部讲,找些重点和常用的

__dirname__filename定时器进程对象global

__dirname(前面有两个下划线):表示获取当前js的文件夹地址,包括自己

console.log(__dirname);--->C:\Users\gyh\Desktop\day2\01.js 01.js就是自己

__filename(前面有两个下划线):表示获取当前js的文件夹的地址,不包括自己

console.log(__filename);--->C:\Users\gyh\Desktop\day2 相比较于__dirname少了01.js,就是地址里面不包括自己

定时器:

var timer = setTimeout(function() { console.log("setTimeout"); },1000); var timer1 = setInterval(function(){ console.log("setInterval") },1000); //定时器的用法和js一样没差别

进程对象:

console.log(process.argv);// 线程 进程 一个进程可以含多个线程 一个线程就是程序执行的路径 console.log(process.arch); //当前系统的架构 32/64

global:全局变量

在node中是没有window的全局对象的,所以我们是无法使用window.alert("xxx"),在node中全局变量就是global,当然全局变量是可以省略的

global.console.log(12345); console.log(12345);

node模块化

为什么我们要学习模块化?比如说有这么一个应用场景,a.js需要调用b.js的方法?那么我们需要如何去应用b.js的方法呢?这时候我们就是用将b.js模块化。

导出模块有两种方式

exports.xxx=xxxmodule.exports=xxx

两中导出方法是有差异的,并且导出方法的不同那么调用方法也是不同的

1.exports.xxx=xxx

//模块b.js function sum(a,b){ return a+b; } //导出模块 exports.sum = sum; //a.js使用b.js的sum方法 var b = require("./b.js"); var res = b.sum(1,2); console.log(res);

2.module.exports=xxx

//模块b.js function sum(a,b){ return a+b; } //导出模块 module.exports= sum; //a.js使用b.js的sum方法 var b = require("./b.js"); console.log(b(1,2));

上面两种方法的值都是3

我们可以看到两种方法的导出方式不同导致调用的方式也不同。那么两者到底有什么区别呢?下面我们来讲解一下

       需要注意的是module.exports和exports这两种方式是不能同时使用的,也就是说只能二选一。

我们可以把两种方式写成一个关系式

      module.exports = {}

      exports = {}

      module.exports===exports--->true

也就是说module.exports和exports所表示的对象是同一个对象,所以会有两种导出的方式。

这也就是为什么最后我们调用的方式不同,因为exports我们是在该对象里添加参数,而module.exports则是重新赋予一个新的对象。

那么我们会问了,为什么我们不能给exports的方法去赋予一个对象?那么我们来试一试。

//模块b.js function sum(a,b){ return a+b; } //导出模块 exports= sum; //a.js使用b.js的sum方法 var b = require("./b.js"); var res = b(1,2); console.log(res);

结果是报错,说找不到该方法。为什么呢?我们不是给exports赋予了一个到处对象?里面不就有方法,为什么还是找不到该方法?

因为是这样子的,导出对象虽然有两种方法,但是最后还是以module.exports所指向的对象为主,一开始exports和module.exports指向的是同一个对象,所以你在给exports的对象添加参数的同时,他们指向的对象至始至终都是同一个,但若你要改变exports的指向对象,而实际导出的却又是module.exports的对象,此时exports和module.exports指向的是两个对象,所以在调用的时候会找不到该方法。

path模块

通过线面模板的导出有了一些认识之后,我们来学习一下node给我们的path模块。

如何引入模块?

var path = require("path");   ------所有node的模块引入都是  require(xxx);

path模块是干什么的呢?主要是用来操作路径的

basenamedirnameextnameformatparseisAbsolutejoinnormalizerelativeresolve

basename

表示获取路径的最后一个部分

const path = require("path"); path.basename('foo/bar/baz/asdf/quux.html');// quux.html path.basename('foo/bar/baz/asdf/quux.html',".html"); // quux path.basename('foo/bar/baz/asdf/quux.html',"html"); // quux. path.basename('foo/bar/baz/asdf/quux.html',".txt");// quux.html

第二个参数表示是过滤掉同样后缀的那部分,就第二个参数的".html",则在结果中忽略".html",若是"html",则忽略"html".

dirname

表示返回当前路径的路径名

const path = require("path") path.dirname("/a/b/c/d");// /a/b/c

extname

表示返回path路径中最后一个部分从.(句号)开始到字符串结束的内容

const path = require("path"); path.extname('foo/bar/baz/asdf/quux.html');// .html path.extname('foo/bar/baz/asdf/quux.txt'); // .txt path.extname('foo/bar/baz/asdf/quux.txt.java'); // .java path.extname('foo/bar/baz/asdf/quux.'); // . path.extname('foo/bar/baz/asdf/quux');// 返回空字符串

parse

该方法就是把一个path的路径转化为一个pathObject对象

const path = require("path"); path.parse(__dirpath); { root: 'C:\\', dir: 'C:\\Users\\gyh\\Desktop', base: 'day4', ext: '', //因为没有后缀名所以为空 name: 'day4' }

format

该方法和parse相对,就是把pathObject对象转化为path的string。

const path = require("path"); let data = { root: 'C:\\', dir: 'C:\\Users\\gyh\\Desktop', base: 'day4.txt', ext: '.txt', name: 'day4' } console.log(path.format(data));//C:\Users\gyh\Desktop\day4.txt

isAbsolute

判断给的路径是不是绝对路径

const path = require("path"); path.isAbsolute('//server'); // true path.isAbsolute('\\\\server'); // true path.isAbsolute('C:/foo/..'); // true path.isAbsolute('C:\\foo\\..'); // true path.isAbsolute('bar\\baz'); // false path.isAbsolute('bar/baz'); // false path.isAbsolute('.'); // false

join

表示拼接路径,路径必须是字符串

const path = require("path"); console.log(path.join('/foo','bar','asc/fg','he','../../'));//\foo\bar\asc\ console.log(path.join('/foo','bar','asc/fg','he','..'));//\foo\bar\asc\\fg console.log(path.join('/foo','bar','asc/fg','he'));//\foo\bar\asc\gf\he console.log(path.join('/foo','bar','asc/fg/','he'));//\foo\bar\asc\gf\he console.log(path.join('/foo','bar','asc/fg/',{},'he'));// 报错

..表示返回到上一级目录

normalize

表示规范路径。就是会将很多连续的分隔符统一变成规范的。

path.win32.normalize('C:temp\\\\/\\/\\/foo/bar');// 'C:\\temp\\foo\\bar' path.normalize('C:\\temp\\\\foo\\bar\\..\\');// 'C:\\temp\\foo\\' path.normalize('/foo/bar//baz/asdf/quux/..');// '/foo/bar/baz/asdf'

relative(from,to)

表示from路径相对于to路径的相对路径

path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb');// 返回: '..\\..\\impl\\bbb'

resolve

将多个路径片段,解析成一个绝对路径

console.log(path.resolve('wwwroot','static_files/png/','../gif/img.gif')); //C:\Users\gyh\Desktop\day4\wwwroot\static_files\gif\img.gif

当前路径是C:\Users\gyh\Desktop\day4,在这个基础上拼接wwwroot->C:\Users\gyh\Desktop\day4\wwwroot,然后在这基础上再添加static_files/png/--->C:\Users\gyh\Desktop\day4\wwwroot\static_files/png,最后返回上一级,找到git的img.gif-->//C:\Users\gyh\Desktop\day4\wwwroot\static_files\gif\img.gif

fs模块

fs模块是文件系统模块,同样的本文也只是介绍些常用的方法,不会讲所有方法一一讲解一遍。

stat

readFile

writeFile

mkdir

readdir

rmdir

createReadStream

createWriteStream

stat(url,callback)

表示获取文件状态。

url当然就是路径了,callback这个回调函数里有两个参数,一个是error,一个是stats。前者表示当获取文件状态发生异常时,error不会空,并且error.code错误码来表示某种错误。stats则表示文件状态,是一个对象。如下

Stats { dev: 1759477673, mode: 16822, nlink: 1, uid: 0, gid: 0, rdev: 0, blksize: undefined, ino: 1125899907036429, size: 0, blocks: undefined, atimeMs: 1540557316105.3225, mtimeMs: 1540557316105.3225, ctimeMs: 1540557316105.3225, birthtimeMs: 1540557316101.1113, atime: 2018-10-26T12:35:16.105Z, mtime: 2018-10-26T12:35:16.105Z, ctime: 2018-10-26T12:35:16.105Z, birthtime: 2018-10-26T12:35:16.101Z }

就比如说size就是表示文件的大小,birthtime表示被创建的时间,birthtimeMs表示被创建的毫秒时间。该对象还有一些方法

stats.isFile() 表示是否是一个普通文件,stats.isDirectory()表示是否是一个文件夹。stat的具体使用如下

const fs = require("fs"); console.log(1); fs.stat("./my",function(error,stat){ if(stat.isFile()){ console.log("isflie"); }else{ console.log("dir"); } console.log(2); console.log(stat); }) console.log(3);

首先stat是异步的,所以log的输出顺序是

如果想要同步获取那么就使用statSync

const fs = require("fs"); // statSync 同步 let fs_sy = fs.statSync("./my");

返回的结果就是stats对象

readFile(url[,options],callback)

表示异步的读取一个文件的内容。

const fs = require("fs"); fs.readFile(__dirname+"/my/demo.txt",{encoding:"utf8",flag:"r"},(error,data)=>{ if(error){ console.log(error); return; } console.log(data.toString()); })

options其实是一个对象,encoding表示字符编码,flag表示文件系统的flag,如r就表示可读。

同样的callback回调返回两个参数,一个是error在读取文件发生错误时返回的信息,data则是读取到的信息。

readFile这是异步的,但也有同步方法也是就是readFileSync,那么返回的结果就是读取的数据

writeFile(url,data[,options],callback)

表示异步给文件写入指定数据

const fs = require("fs"); let strpath = path.join(__dirname,"./my/demo.txt"); fs.writeFile(strpath,"hello word1111","utf8",function(err){ if (err) { console.log(err); }else{ console.log("文件写入成功"); } })

options表示一个对象,有三个参数,encoding表示字符编码,flag表示文件系统flag,mode表示文件的权限,当输入字符串时默认视为encoding。

此时的callback回调只返回一个error。

同样的写入数据可以同步就是writeFileSync,返回的是underfined。同步也好异步也好当找不到要写入的文件的时候,都回去创建该文件。

mkdir

该方法是异步创建文件夹

const fs = require("fs"); //添加文件夹 fs.mkdir("./mkdir",(err)=>{ console.log(err); })

同样的该方法是异步的,想要同步创建文件及则用mkdirSync方法

readdir

该方法则是用来遍历指定目录下所有文件。

const fs = require("fs"); //遍历目录 fs.readdir(__dirname,(err,fils)=>{ if(err){ return ; } console.log(fils); })

我们可以来看看输出

[ 'jquery-1.12.4.js', 'my', 'my.rar', 'myhtml.html', 'myjs.js', 'myjs1.js', 'myjs2.js', 'myjs3.js', 'myjs4.js' ]

连文件类型都是会显示出来的

rmdir

该方法和mkdir对应,就是删除文件夹

const fs = require("fs"); //删除文件 fs.rmdir(path.join(__dirname,"mkdir"),(err)=>{ console.log(err); })

createReadStream

将一个文件的内容解析成输入数据流,并返回该数据流  readStream。

const fs = require("fs"); const path = require("path"); //大文件的转数据流 let readStream = fs.createReadStream("./my/demo.txt","utf8"); //解析数据流,给流绑定解析时间 readStream.on("data",(chunk)=>{ console.log(chunk.length); console.log(chunk); }) //给流绑定数据被解析完的回调 readStream.on("end",()=>{ console.log("is end"); })

createWriteStream

将一个文件解析成一个输出数据流,并返回该数据流,writeStream

const fs = require("fs"); const path = require("path"); //大文件的操作 let readStream = fs.createReadStream("./my.rar"); let writeStream = fs.createWriteStream("./my_write.rar"); readStream.on("data",(chunk)=>{ //解析数据 console.log(chunk.length); writeStream.write(chunk); //方法1:将解析出来的数据写入到输出流中 }) readStream.on("end",()=>{ console.log("is end"); }) readStream.pipe(writeStream);//方法2:将输入流和输出流相绑定

综合案例

平时在开发项目中,我们都需要去创建很多文件比如说css img js 等,现在我们就可以通过path和fs模块去快递生产这些基本项目结构。

const fs = require("fs"); const path = require("path"); let index_content = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> </body> </html> `; const root = __dirname; let pathData = { rootName:"buildDemo", data:[{ name:"js", type:"dir" },{ name:"css", type:"dir" },{ name:"img", type:"dir" },{ name:"index.html", type:"file" }] } fs.mkdir(path.join(root,pathData.rootName),(err)=>{ if(err){ return; } pathData.data.forEach((item,index)=>{ if(item.type=="dir"){ fs.mkdirSync(path.join(root,pathData.rootName,item.name)); }else if(item.type=="file"){ fs.writeFileSync(path.join(root,pathData.rootName,item.name),index_content); } }) })

本章节目标已完成,接下来会讲解npm相关语法,如有表达错的请谅解,并请提出指出,且修改错误,望能共同进步。

 

转载请注明原文地址: https://www.6miu.com/read-5038312.html

最新回复(0)