本文主要经过对JavaScript中数字数据与二进制数据之间的转换,让读者可以了解在JavaScript中如何对数字类型(包括但不限于Number类型)进行处理。javascript
二进制数据在平常的JavaScript中不多遇到,可是当你使用WebSocket与后端进行数据交互时,就有可能会用到二进制的数据格式。所以,为了更好的理解本系列中以后发布的关于WebSocket传输二进制相关的内容,咱们有必要了解二进制数据在JavaScript中是如何进行操做和存储的。html
本文内容主要为:java
本文与WebSocket并没有太强关联,不过做为在WebSocket中传递二进制数据的基础知识储备,所以放入了此系列当中。后端
若是读者对WebSocket并不了解,或者说不明白它的使用场景和细节,能够阅读个人前一篇博客——WebSocket系列之基础知识入门篇。函数
若是读者想了解String类型与二进制之间的处理和转换,能够于都WebSocket系列稍后发布的文章(文章发布后会替换此段)。源码分析
若是读者想了解在WebSocket中如何进行二进制的传递和解析,能够阅读WebSocket系列稍后发布的文章(文章发布后会替换此段)。post
了解了为何须要使用二进制数据,咱们来看下,在JavaScript中如何存储和操做二进制数据。学习
首先,咱们要介绍下在JavaScript中用来存储二进制数据的ArrayBuffer
。code
ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。
在MDN的文档中,咱们可以看到ArrayBuffer
的介绍。它是在JavaScript中用来进行二进制数据存储的一种数据对象。htm
下面咱们经过一个示例来简单介绍下ArrayBuffer相关操做。
const buffer = new ArrayBuffer(8); buffer.byteLength; // 结果为8
上面的示例经过建立一个长度为8Byte的二进制数据缓冲区。缓冲区只是一个数据存储的空间,如何对这个存储空间进行读取,彻底取决于使用者。例如:8个字节能够当成是2个Int类型的数据,也能够是一个Long类型的数据,或者4个Short型的数据。
看完了存储数据的ArrayBuffer
,咱们来看下数据读写的DataView
。
DataView 视图是一个能够从
ArrayBuffer
对象中读写多种数值类型的底层接口,在读写时不用考虑平台字节序问题。
这个是在MDN中关于DataView的介绍。DataView提供了大量的API接口来进行数据的读和写操做,咱们在后三章将会举例进行说明。可是,首先咱们得先看下说明中提到的字节序问题。
在现有的计算机体系中,有两种字节序:
上面所说的顺序均是针对多字节对象而言,如Int类型,Long类型。以Int类型数据0x1234
为例,若是是大端字节序,那么数据从人类对数值的一般写法上来看就是0x1234
;若是是小端字节序,那么从人类对数值的一般写法上来看,应该写成0x3412
。
对于单字节对象如Byte类型数据而言,没有字节序一说。
在不一样的平台中,可能使用不一样的字节序,这就是所谓的字节序问题。DataView所谓的在读写时不须要考虑平台字节序问题是指:同时使用DataView进行写入和读取的数据保持一致。
对ArrayBuffer和DataView有了一个大概的了解,下面让咱们来看下它是如何进行二进制数据操做的。
本章,我以Short类型和Int类型为例,介绍下相关操做步骤。
let buffer = new ArrayBuffer(6); // 初始化6个Byte的二进制数据缓冲区 let dataView = new DataView(buffer); dataView.setInt16(0, 3); // 从第0个Byte位置开始,放置一个数字为3的Short类型数据(占2 Byte) dataView.setInt32(2, 15); // 从第2个Byte位置开始,放置一个数字为15的Short类型数据(占4 Byte)
经过上面的示例,咱们一共初始化了6个Byte的存储空间,使用1个Short类型(占2 Byte)和一个Int类型(占4 Byte)的数据进行填充。
DataView还提供了许多的API接口来进行其余数据类型的处理,如无符号型,浮点数等。他们的使用方法和上面介绍的API相同,咱们在这里就不一一进行介绍了,但愿了解更多API接口的读者能够查看MDN文档。
经过DataView提供的API接口,咱们知道了如何处理Short类型、Int类型、Float类型和Double类型。那么,若是是对于Long类型这种原生API中没有提供处理函数的数据类型,咱们应该如何处理呢?
首先,咱们须要理解Long数据类型的结构,它是由一个高位的4个Byte和低位的4个Byte组成的数据类型。由于Long类型表示的范围比Number类型大,因此咱们在JavaScript中是使用了两个Number类型(即Int类型)的对象来表示Long类型数据,相关的具体细节能够见我以前的博客Long.js源码分析与学习。
理解了JavaScript中如何存储Long类型,咱们就知道若是对其进行存储。
import Long from 'long'; let long = Long.fromString('123'); let buffer = new ArrayBuffer(8); let dataView = new DataView(buffer); dataView.setInt32(0, long.high); // 采用大端字节序放置 dataView.setInt32(4, long.low);
经过上面的示例,咱们将一个Long类型的数据拆分红了两个Int类型的数据,按照大端字节序放入到了ArrayBuffer中。同理,若是是想按照小端字节序放置,只须要将数据进行部分处理后再放入便可,在此我就不过多介绍了。
当你知道了如何将数据转换为ArrayBuffer中存储的二进制数据后,就可以简单推测出如何进行反向操做——将数据从ArrayBuffer中读取出来,再转换成JavaScript中经常使用数据类型。
import Long from 'long'; let buffer = new ArrayBuffer(14); // 初始化14个Byte的二进制数据缓冲区 let dataView = new DataView(buffer); let long = Long.fromString('123'); // 数据写入过程 dataView.setInt16(0, 3); // 从第0个Byte位置开始,放置一个数字为3的Short类型数据(占2 Byte) dataView.setInt32(2, 15); // 从第2个Byte位置开始,放置一个数字为15的Short类型数据(占4 Byte) dataView.setInt32(6, long.high); // 采用大端字节序放置 dataView.setInt32(10, long.low); // 数据读取过程 let shortNumber = dataView.getInt16(0); let intNumber = dataView.getInt32(2); let longNumber = Long.fromBits(dataView.getInt32(10), dataView.getInt32(6)); // 根据大端字节序读取,该构造函数入参依次为:低16位,高16位
经过上面的示例,咱们将一串二进制数据转换成为了JavaScript中通用的数据类型。
经过使用ArrayBuffer和DataView,咱们可以快速的将数字数据从二进制转换为JavaScript经常使用数据类型如Int、Short等;同时,咱们也能够将这些数据类型转换为二进制数据。有了这些基础知识,咱们就可以理解在以后的博客中讲到的关于使用WebSocket进行二进制数据传递的过程和处理逻辑。
下一篇博客咱们将介绍String类型相关的二进制处理与转换操做,有兴趣的同窗能够关注留意下相关内容。