## 一、Buffer
  Buffer是一種Node的內置類型,不需要通過require()函數額外引入。它能讀取和寫入二進制數據,常用于解析網絡數據流、文件等。
**1)創建**
  通過new關鍵字初始化Buffer對象的方式已經被廢棄,下面的代碼都已經過時。
~~~javascript
new Buffer(array)
new Buffer(arrayBuffer[, byteOffset[, length]])
new Buffer(buffer)
new Buffer(size)
new Buffer(string[, encoding])
~~~
  目前有兩種方式創建Buffer對象,第一種是通過alloc()或allocUnsafe()兩個靜態方法,語法如下。
~~~javascript
Buffer.alloc(size[, fill[, encoding]])
Buffer.allocUnsafe(size)
~~~
  alloc()方法可接收三個參數,后兩個是可選的。第一個參數是長度,第二個參數是預填充的值,第三個參數是字符編碼,默認值是“utf8”。
~~~
const buf1 = Buffer.alloc(10);
const buf2 = Buffer.alloc(10, "A");
const buf3 = Buffer.alloc(10, "A", "ascii");
~~~
  如果打印buf3,那么得到的將是一組十六進制數據,而非難以閱讀的二進制數據,如下所示。
~~~
<Buffer 41 41 41 41 41 41 41 41 41 41>
~~~
  注意,Buffer的大小在創建時確定,后面也無法更改,其類型可由Buffer.isBuffer()辨別。當前Node支持的字符編碼有6種:
  (1)ascii:僅適用于7位的ASCII數據。
  (2)utf8:多字節編碼的Unicode字符。許多網頁和其它文檔格式都在使用UTF-8。
  (3)utf16le/ucs2:2或4個字節,小端序編碼的Unicode字符。支持代理對(U+10000至U+10FFFF)。
  (4)base64:Base64編碼,一種基于64個可打印字符來表示二進制數據的表示方法。
  (5)latin1/binary:一種可編碼成單字節字符串的方法。
  (6)hex:將每個字節編碼成兩個十六進制的字符。
  allocUnsafe()是一個不安全的方法,因為它分配的內存片段是未初始化的,即沒有被清零。雖然這種設計性能優越,但分配的內存中可能會包含舊數據。
  第二種是通過Buffer.from()方法創建Buffer對象,它的參數可以是數組、字符串、Buffer對象等,如下所示。
~~~
const buf = Buffer.from("A");
console.log(buf); //<Buffer 41>
~~~
**2)轉換編碼**
  在讀取文件時,可通過toString()方法將Buffer對象轉換成字符串,如下所示,默認是UTF-8格式。
~~~
const fs = require('fs');
fs.readFile('./demo.txt', (err, buf) => {
buf.toString(); //"你好,Node.js"
buf.toString("base64"); //"5L2g5aW977yMTm9kZS5qcw=="
});
~~~
## 二、流
  Node中的stream模塊用于處理流式數據,許多內置的核心模塊都在其內部實現了流操作,流還適用于網絡傳輸、JSON解析器、RFC(遠程調用)等。流包括四個抽象類:
  (1)Readable:可讀流,讀取底層的I/O數據源。
  (2)Writeable:可寫流,將數據寫入到目標中。
  (3)Duplex:雙工流,即可讀也可寫。
  (4)Transform:轉換流,會修改數據的雙工流。
**1)pipe()**
  在可讀流中,包含一個管道方法:pipe(),它的作用是關聯可讀流與可寫流,讓數據通過管道從可讀流進入到可寫流中。pipe()方法能接收一個Writable對象,并返回對目標流的引用,從而可形成鏈式調用。
  在下面的示例中,會將origin.txt中的數據通過管道寫入到target.txt文件中,調用文件模塊的createReadStream()方法能得到一個Readable對象。
~~~
const fs = require('fs');
const readable = fs.createReadStream('./origin.txt');
const writable = fs.createWriteStream('./target.txt');
readable.pipe(writable);
~~~
**2)事件**
  以可讀流為例,它的data事件可在接收到數據塊后觸發,而end事件會在流沒有數據時觸發。在下面的示例中,origin.txt文件包含的內容是“hello Node.js”。
~~~
const fs = require('fs');
const readable = fs.createReadStream('./origin.txt', {highWaterMark: 2});
readable.on("data", (chunk) => {
console.log(`接收到 ${chunk.length} 個字節的數據`, chunk.toString());
});
readable.on("end", () => {
console.log("結束接收");
});
~~~
  在調用createReadStream()方法時,包含一個highWaterMark屬性,其默認值為64KB,它的作用是限制可緩沖的字節數。當定義為2后,每接收2個字節的數據,就會觸發data事件,打印結果如下所示。
~~~
接收到 2 個字節的數據 he
接收到 2 個字節的數據 ll
接收到 2 個字節的數據 o
接收到 2 個字節的數據 No
接收到 2 個字節的數據 de
接收到 2 個字節的數據 .j
接收到 1 個字節的數據 s
結束接收
~~~
  可讀流還包含一個error事件,用于監聽異常,其事件處理程序會接收一個Error對象。在下面的示例中,會讀取不存在的文件,從而觸發error事件。
~~~
const readable = fs.createReadStream('./demo.txt');
readable.on("error", (err) => {
console.log(err); //打印錯誤信息
});
~~~
**3)實現流**
  當實現自定義的流時,需要繼承四個抽象類中的一個,表1列出了四個抽象類需要實現的方法。
:-: 
  下面是一個自定義可寫流的例子,\_write()方法中的encoding是一個字符串,表示字符編碼。
~~~
const { Writable } = require('stream');
class MyWritable extends Writable {
constructor(options) {
super(options);
}
_write(chunk, encoding, callback) {
if (encoding === "buffer") {
callback();
}
}
}
~~~
## 三、EventEmitter
  Node的事件模塊目前只包含一個EventEmitter類(即事件觸發器),所有能觸發事件的對象都是EventEmitter類的實例。EventEmitter通常被用作基類,在Node內部,凡是提供事件機制的模塊都會繼承它。
  在下面的示例中,聲明了一個EventEmitter實例,on()方法用于注冊監聽器,emit()方法用于觸發事件。在調用emit()方法時,傳遞了自定義的type參數。
~~~
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('click', (type) => {
console.log(`觸發${type}事件`);
});
myEmitter.emit('click', "點擊");
~~~
  注意,可注冊多個相同名稱的事件,監聽器會按照添加順序依次調用。事件模塊還提供了很多其它方法,例如off()用于解除事件綁定,once()可以只監聽一次事件。
*****
> 原文出處:
[博客園-Node.js躬行記](https://www.cnblogs.com/strick/category/1688575.html)
[知乎專欄-Node.js躬行記](https://zhuanlan.zhihu.com/pwnode)
已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎瀏覽。

推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
- ES6
- 1、let和const
- 2、擴展運算符和剩余參數
- 3、解構
- 4、模板字面量
- 5、對象字面量的擴展
- 6、Symbol
- 7、代碼模塊化
- 8、數字
- 9、字符串
- 10、正則表達式
- 11、對象
- 12、數組
- 13、類型化數組
- 14、函數
- 15、箭頭函數和尾調用優化
- 16、Set
- 17、Map
- 18、迭代器
- 19、生成器
- 20、類
- 21、類的繼承
- 22、Promise
- 23、Promise的靜態方法和應用
- 24、代理和反射
- HTML
- 1、SVG
- 2、WebRTC基礎實踐
- 3、WebRTC視頻通話
- 4、Web音視頻基礎
- CSS進階
- 1、CSS基礎拾遺
- 2、偽類和偽元素
- 3、CSS屬性拾遺
- 4、浮動形狀
- 5、漸變
- 6、濾鏡
- 7、合成
- 8、裁剪和遮罩
- 9、網格布局
- 10、CSS方法論
- 11、管理后臺響應式改造
- React
- 1、函數式編程
- 2、JSX
- 3、組件
- 4、生命周期
- 5、React和DOM
- 6、事件
- 7、表單
- 8、樣式
- 9、組件通信
- 10、高階組件
- 11、Redux基礎
- 12、Redux中間件
- 13、React Router
- 14、測試框架
- 15、React Hooks
- 16、React源碼分析
- 利器
- 1、npm
- 2、Babel
- 3、webpack基礎
- 4、webpack進階
- 5、Git
- 6、Fiddler
- 7、自制腳手架
- 8、VSCode插件研發
- 9、WebView中的頁面調試方法
- Vue.js
- 1、數據綁定
- 2、指令
- 3、樣式和表單
- 4、組件
- 5、組件通信
- 6、內容分發
- 7、渲染函數和JSX
- 8、Vue Router
- 9、Vuex
- TypeScript
- 1、數據類型
- 2、接口
- 3、類
- 4、泛型
- 5、類型兼容性
- 6、高級類型
- 7、命名空間
- 8、裝飾器
- Node.js
- 1、Buffer、流和EventEmitter
- 2、文件系統和網絡
- 3、命令行工具
- 4、自建前端監控系統
- 5、定時任務的調試
- 6、自制短鏈系統
- 7、定時任務的進化史
- 8、通用接口
- 9、微前端實踐
- 10、接口日志查詢
- 11、E2E測試
- 12、BFF
- 13、MySQL歸檔
- 14、壓力測試
- 15、活動規則引擎
- 16、活動配置化
- 17、UmiJS版本升級
- 18、半吊子的可視化搭建系統
- 19、KOA源碼分析(上)
- 20、KOA源碼分析(下)
- 21、花10分鐘入門Node.js
- 22、Node環境升級日志
- 23、Worker threads
- 24、低代碼
- 25、Web自動化測試
- 26、接口攔截和頁面回放實驗
- 27、接口管理
- 28、Cypress自動化測試實踐
- 29、基于Electron的開播助手
- Node.js精進
- 1、模塊化
- 2、異步編程
- 3、流
- 4、事件觸發器
- 5、HTTP
- 6、文件
- 7、日志
- 8、錯誤處理
- 9、性能監控(上)
- 10、性能監控(下)
- 11、Socket.IO
- 12、ElasticSearch
- 監控系統
- 1、SDK
- 2、存儲和分析
- 3、性能監控
- 4、內存泄漏
- 5、小程序
- 6、較長的白屏時間
- 7、頁面奔潰
- 8、shin-monitor源碼分析
- 前端性能精進
- 1、優化方法論之測量
- 2、優化方法論之分析
- 3、瀏覽器之圖像
- 4、瀏覽器之呈現
- 5、瀏覽器之JavaScript
- 6、網絡
- 7、構建
- 前端體驗優化
- 1、概述
- 2、基建
- 3、后端
- 4、數據
- 5、后臺
- Web優化
- 1、CSS優化
- 2、JavaScript優化
- 3、圖像和網絡
- 4、用戶體驗和工具
- 5、網站優化
- 6、優化閉環實踐
- 數據結構與算法
- 1、鏈表
- 2、棧、隊列、散列表和位運算
- 3、二叉樹
- 4、二分查找
- 5、回溯算法
- 6、貪心算法
- 7、分治算法
- 8、動態規劃
- 程序員之路
- 大學
- 2011年
- 2012年
- 2013年
- 2014年
- 項目反思
- 前端基礎學習分享
- 2015年
- 再一次項目反思
- 然并卵
- PC網站CSS分享
- 2016年
- 制造自己的榫卯
- PrimusUI
- 2017年
- 工匠精神
- 2018年
- 2019年
- 前端學習之路分享
- 2020年
- 2021年
- 2022年
- 2023年
- 2024年
- 日志
- 2020