JavaScript 中的二进制
JavaScript 中的 TypedArray 与 Buffer
TypedArray
这是 ES2015(又称 ES6) 中新出的一个接口,不能直接被实例化。
因为这个接口就是一个抽象接口,就像 Java 中的抽象接口一样,是不能被实例化的,只能实例化实现该接口的子类。Uint8Array 就是实现 TypedArray 接口的一个子类。
就 Nodejs 而言, 可以使用 Buffer 操作二进制数据, 那对前端 JS 而言, 在 TypeArray 出现之前, 是没有可以直接操作二进制数据的类的。
所以 TypeArray 接口的作用是操作二进制数据。
ArrayBuffer
TypedArray 的作用是操作二进制数据, 其内部还有一个 buffer 属性, 这个 buffer 就是 ArrayBuffer 实例.。ArrayBuffer 就存储了要操作的二进制数据。
因此可以知道, TypedArray 是一个操作二进制数据的接口, 内部的 ArrayBuffer 存储了要操作的二进制数据。
Unit8Array
实现了 TypedArray 接口的子类有很多, Unit8Array 就是其中一个, 这个子类表示: 数组中的每一个元素都是 8 个二进制位(1 个字节)的无符号整数。
无符号的含义是, 该二进制的首位不表示符号位. 而对于有符号的二进制位, 首位 1 表示负数。
所以 Unit8Array 中每个元素的取值范围应该是 0 ~ 255
。
Name | Value | Value |
---|---|---|
二进制表示 | 10001111 | 00001111 |
无符号 | 143 | 15 |
有符号 | -15 | 15 |
Buffer
Buffer 在前端 JS 中并不存在, 是 Node 专门提供用来操作二进制数据的, 因为对于后端来说, 操作二进制数据是比较基础的操作。
而在 ES6 的 TypeArray 推出之后, 自 Node 3.0.0 版本开始, Buffer 继承自 Unit8Array, 相当于是对 ES6 中的 TypeArray 做兼容。
总结
- TypedArray: ES6 提供的用来操作二进制数据的接口, 具体由子类实现。
- ArrayBuffer: 在 TypedArray 内部, 存储了要操作的二进制数据。
- Unit8array: 实现 TypedArray, 每个元素都占据一个字节。
- Buffer: Node 中才有, 继承自 Unit8array, 拥有更多强大的二进制数据操作。
附:JavaScript 进制转换
js
parseInt(num).toString(2); // 十进制转二进制
parseInt(num).toString(8); // 十进制转八进制
parseInt(num).toString(16); // 十进制转十六进制
parseInt(num, 2); // 二进制转十进制
parseInt(num, 8); // 八进制转十进制
parseInt(num, 16); // 十六进制转十进制
parseInt(num, 2).toString(8); // 二进制转八进制
parseInt(num, 8).toString(2); // 八进制转二进制
parseInt(num, 2).toString(16); // 二进制转十六进制
parseInt(num, 16).toString(2); // 十六进制转二进制
parseInt(num, 8).toString(16); // 八进制转十六进制
parseInt(num, 16).toString(8); // 十六进制转八进制
附:NodeJS base64 转 buffer
js
// 将base64编码的二进制报文解析成buffer
const b = new Buffer.from("KA==", "base64");
// 将buffer解析成hex字符串
const s = b.toString("hex");
// 将hex字符串解析成10进制整数
console.log(parseInt(s, 16));
附:JavaScript 二进制数组的几种应用
AJAX
XMLHttpRequest 第一版 responseType 属性默认为 text。
XMLHttpRequest 第二版 XHR2 允许服务器返回二进制数据,这时分成两种情况:
- 已知二进制数据类型:responseType 设为 arraybuffer。
- 未知二进制数据类型:responseType 设为 blob。
js
const xhr = new XMLHttpRequest();
xhr.open("GET", someUrl);
xhr.responseType = "arraybuffer";
xhr.onload = function () {
let arrayBuffer = xhr.response;
// ···
};
xhr.send();
Canvas
首先看下面的例子:
js
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const uint8ClampedArray = imageData.data; // Canvas 元素输出的二进制像素数据,也是 TypedArray 数组
需要注意的是:Uint8ClampedArray 这个类型是针对 Canvas 元素的专有类型,它是专门针对颜色,取值只能是 0~255。
WebSocket
WebSocket 可以通过 ArrayBuffer,发送或接收二进制数据。
js
const socket = new WebSocket("ws://127.0.0.1:8081");
socket.binaryType = "arraybuffer";
// 等待直到 socket 打开
socket.addEventListener("open", function (event) {
// 发送二进制数据
const typedArray = new Uint8Array(4);
socket.send(typedArray.buffer);
});
// 接受二进制数据
socket.addEventListener("message", function (event) {
const arrayBuffer = event.data;
// ···
});
Fetch API
Fetch API 取回的数据,就是 ArrayBuffer 对象。
js
fetch(url)
.then(function (request) {
return request.arrayBuffer();
})
.then(function (arrayBuffer) {
// ...
});
File API
如果知道一个文件的二进制数据类型,也可以将这个文件读取为 ArrayBuffer 对象。
js
const fileInput = document.getElementById("fileInput");
const file = fileInput.files[0];
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function () {
const arrayBuffer = reader.result;
// ···
};