簡介
?? Node.js 是一個(gè)基于 Chrome V8 引擎的 JavaScript 運(yùn)行環(huán)境。Node.js 使用了一個(gè)事件驅(qū)動、非阻塞式 I/O的模型,使其輕量又高效。Node.js 的包管理器 npm,是全球最大的開源庫生態(tài)系統(tǒng)。
安裝以及運(yùn)行環(huán)境
?? Node.js最新版可在官網(wǎng)下載,傻瓜式安裝后我們可打開命令行工具,輸入node -v和npm -v后顯示顯示對應(yīng)版本號后說明已經(jīng)安裝成功。在開發(fā)過程中我使用的是webstorm編輯器,該編輯器功能強(qiáng)大,是前端使用比較普遍的一類編輯器。為支持我們快捷開發(fā),webstorm為我們提供了一系列快捷的設(shè)置選項(xiàng),如點(diǎn)擊webstotm中file -- Setting -- Languages -- JavaScript可設(shè)置編輯器支持最新語言版本為ES6,點(diǎn)擊file -- Setting -- Node.js and NPM --Enable可設(shè)置node命令。設(shè)置完成后,我們在編輯器中輸入
let a = 10 ;
console.log(a);
然后點(diǎn)擊Run,結(jié)果就出來了。

Node.js基本知識
一、模塊的使用
? ? Node.js有一個(gè)簡單的模塊加載系統(tǒng),在 Node.js 中,文件和模塊是一一對應(yīng)的(每個(gè)文件被視為一個(gè)獨(dú)立的模塊)。我們分別通過export和require來導(dǎo)出模塊以及引用模塊。
circle.js
let { PI } = Math;
exports.area = (r) => PI * r * r;
foo.js
const circle = require('./circle.js');
console.log(circle.area(4));
? ?輸出結(jié)果為 50.26548245743669;
?? 值得注意的是,module.exports和exports都可以導(dǎo)出模塊,他們有什么區(qū)別呢?用一句話來概括就是,require能看到的只有module.exports這個(gè)對象,它是看不到exports對象的,而我們在編寫模塊時(shí)用到的exports對象實(shí)際上只是對module.exports的引用。實(shí)際上如下:
var module = {
exports:{
name:"我是module的exports"屬性
}
};
var exports = module.exports;//exports是對module.exports的引用.
//他們是指向同一塊內(nèi)存下的數(shù)據(jù)
? ?通常情況下,我們不會直接對exports賦值,而是把一個(gè)變量掛載到exports上,因?yàn)橹苯淤x值exports會指向新的地址,和原來的地址沒有了關(guān)系,起不到引用的作用了。
二、常用API
global -全局變量
??全局變量是在所有變量均可以使用。下面介紹一些常用的變量。
__dirname 當(dāng)前模塊的文件夾名稱;
__filename當(dāng)前模塊的文件夾名稱解析后的絕對路徑;
exports對于module.exports的更簡短的引用形式;
module對當(dāng)前模塊的引用,module.exports用于指定一個(gè)模塊所導(dǎo)出的內(nèi)容;
require引入模塊;
我們可以通過打印來查詢?nèi)肿兞坷锩娴木唧w內(nèi)容,例如 module,打印出為
Module {
id: '.',
exports: {},
parent: null,
filename: 'C:\\Users\\Administrator\\Desktop\\temporary\\node\\foo.js',
loaded: false,
children:
[ Module {
id: 'C:\\Users\\Administrator\\Desktop\\temporary\\node\\circle.js',
exports: [Object],
parent: [Circular],
filename: 'C:\\Users\\Administrator\\Desktop\\temporary\\node\\circle.js',
loaded: true,
children: [],
paths: [Object] } ],
paths:
[ 'C:\\Users\\Administrator\\Desktop\\temporary\\node\\node_modules',
'C:\\Users\\Administrator\\Desktop\\temporary\\node_modules',
'C:\\Users\\Administrator\\Desktop\\node_modules',
'C:\\Users\\Administrator\\node_modules',
'C:\\Users\\node_modules',
'C:\\node_modules' ] }
node.js提供了path模塊用于處理文件與目錄路徑;
const path = require('path');
具體使用見官網(wǎng)。
Buffer
??JavaScript 語言自身只有字符串?dāng)?shù)據(jù)類型,沒有二進(jìn)制數(shù)據(jù)類型。Buffer 類,該類用來創(chuàng)建一個(gè)專門存放二進(jìn)制數(shù)據(jù)的緩存區(qū)。一個(gè) Buffer 類似于一個(gè)整數(shù)數(shù)組,但它對應(yīng)于 V8 堆內(nèi)存之外的一塊原始內(nèi)存。Buffer對象占用的內(nèi)存空間是不計(jì)算在Node.js進(jìn)程內(nèi)存空間限制上的,因此,我們也常常會使用Buffer來存儲需要占用大量內(nèi)存的數(shù)據(jù):
const buf = Buffer.from('hello world', 'ascii');
// 輸出 68656c6c6f20776f726c64
console.log(buf.toString('hex'));
// 輸出 aGVsbG8gd29ybGQ=
console.log(buf.toString('base64'));
我們可以用Buffer.alloc(size[,fill[,encoding])來初始化一個(gè)buffer類:
const buf = Buffer.alloc(5,'abcde');
console.log(buf);
//輸出 <Buffer 61 62 63 64 65>
當(dāng)輸入字符串長度大于Buffer指定長度,字符串會被按長度折斷;當(dāng)輸入字符串長度不足Buffer指定長度,輸出內(nèi)容會按字符重復(fù)拼接。
const buf = Buffer.alloc(5,'abcdef');
console.log(buf);
console.log(buf.toString())
//輸出<Buffer 61 62 63 64 65>
//輸出 abcde
const buf = Buffer.alloc(5,'ab');
console.log(buf);
console.log(buf.toString())
//輸出<Buffer 61 62 61 62 61>
//輸出 ababa
注意一個(gè)漢字占有3個(gè)Buffer長度。
Buffer.concat(list[, totalLength])返回一個(gè)合并了list中所有Buffer實(shí)例的新建的Buffer。
fs
??fs是node.js對文件以及文件夾進(jìn)行操作的方法。
??監(jiān)聽fs.watch:
const fs = require('fs');
fs.watch('./circle.js',function (eventType , filename) {
if(eventType ==='rename'){
///
}else if(eventType ==='change'){
///
}
})
相對穩(wěn)定一些的是watchFile()這個(gè)方法,文檔中介紹原理是輪詢(每隔一個(gè)固定的時(shí)間去檢查文件是否改動)。而且這個(gè)時(shí)間間隔是可以通過參數(shù)設(shè)置的。watch()這個(gè)方法是通過監(jiān)聽操作系統(tǒng)提供的各種“事件”(內(nèi)核發(fā)布的消息)實(shí)現(xiàn)的。這個(gè)不同的平臺實(shí)現(xiàn)的細(xì)節(jié)不一致,導(dǎo)致這個(gè)方法不能保證在所有平臺上可用(而且經(jīng)過實(shí)驗(yàn)發(fā)現(xiàn)在Mac上行為不正常,內(nèi)容的改動只能觸發(fā)一次回調(diào),再改動watch()就沒動靜了)。
??讀取fs.readFile(path[, options], callback):
const fs = require('fs');
fs.readFile('./circle.js',(err,data) =>{
if(err) throw err;
console.log(data.toString());
})
??寫入fs.writeFile(file, data[, options], callback):
const fs = require('fs');
fs.writeFile('./input.txt',"希望的田野上",function (err) {
if(err) throw err ;
console.log("寫入成功!");
})
??參數(shù)里面flag如果為w,則把原來內(nèi)容抹去重寫,如果為a,則是在內(nèi)容后面追加。fs還包括同步寫入讀取文件,創(chuàng)建刪除文件以及文件夾等操作。
??自動化構(gòu)建在前端非常普遍,我們可以用fs實(shí)現(xiàn)簡單的自動化構(gòu)建前端項(xiàng)目。代碼如下:
const fs = require('fs');
const indexContent = '<!doctype html>\r'+
'<html lang="en">\r'+
'<head>\r'+
'\t<meta charset="UTF-8">\r'+
'\t<meta name="viewport"'+
'content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">\r'+
'\t<meta http-equiv="X-UA-Compatible" content="ie=edge">\r'+
'\t<title>Document</title>\r'+
'</head>\r'+
'<body>\r'+
'\t<h1>這是首頁</h1>\r'+
'</body>\r'+
'</html>\r';
const projectData = {
name:"gallon",
fileData:[
{
name:"css",
type:"dir"
},
{
name:"image",
type:"dir"
},
{
name:"js",
type:"dir"
},
{
name:"index.html",
type:"file",
content:indexContent
},
]
};
if(projectData.name){
fs.mkdirSync(projectData.name)//生成項(xiàng)目文件夾
const fileData = projectData.fileData;
if(fileData && fileData.forEach){
fileData.forEach(function (f) {
f.path = projectData.name + '/' + f.name;
f.content = f.content || '';
if(f.type == "dir"){
fs.mkdirSync(f.path);
}else if(f.type == 'file'){
fs.writeFileSync(f.path, f.content);
}
})
}
}
生成結(jié)構(gòu)如下:

??我們也可以通過
fs進(jìn)行代碼合并:foo.js
const fs = require('fs');
const fileDir = './source';
fs.watch(fileDir,function (eventType,filename) {
fs.readdir('./source',function (err,fileList) {
if(err) throw err;
let content = '';
fileList.forEach(function (f) {
content += fs.readFileSync(fileDir + '/' + f) + '\r';
});
fs.writeFile('./app.js',content ,function (err) {
if(err) throw err ;
console.log("合并完成");
})
})
});
??當(dāng)項(xiàng)目下文件發(fā)生變化的時(shí)候,即會生成app.js。

test1.js
window.onload = function () {
alert(13);
};
test2.js
window.onload = function () {
alert(2);
};
test3.js
window.onload = function () {
alert(10);
};
生成app.js
window.onload = function () {
alert(13);
};
window.onload = function () {
alert(2);
};
window.onload = function () {
alert(10);
};