ES6学习笔记---二进制数组(概念)

CoffeeCode
• 阅读 5890

二进制数组由三类对象组成:

  • ArrayBuffer对象:代表原始的二进制数据。

  • TypedArray视图:用来读写简单类型的二进制数据。

  • DataView视图:用来读写复杂类型的二进制数据。

下面详细了解一下它们的用法:

1. ArrayBuffer 对象

它不能直接读写,只能通过(TypedArrayDataView)来读写。

ArrayBuffer也是一个构造函数,可以分配一段可以存放数据的连续内存区域。

例如我想生成一段32字节的内存区域,每个字节的值默认都是0,就可以这样创建:

var buf = new ArrayBuffer(32);

ArrayBuffer.prototype.byteLength

byteLength:是ArrayBuffer实例的属性,返回所分配的内存区域的字节长度。

var buffer = new ArrayBuffer(32);
buffer.byteLength     // 32

需要注意的是:如果你想分配一块比较大的内存区域,需要检查是否分配成功,因为可能没有那么多的连续空余内存。

if(buffer.byteLength === n){
    //成功
}else{
    //失败
}

ArrayBuffer.prototype.slice()

slice:有两个参数,第一个参数表示开始拷贝的字节序号(包含此字节),第二个参数表示截止拷贝的字节序号(不含此字节),如果省略第二个参数,则默认截止到原ArrayBuffer对象的结尾。

slice:是ArrayBuffer实例的一个方法,允许将内存区域的一部分,拷贝生成一个新的ArrayBuffer对象。

var buffer = new ArrayBuffer(8);
var newBuffer = buffer.slice(0, 3);
//拷贝`buffer`对象的前三个字节(从0到3前结束),生成一个新的ArrayBuffer对象:newBuffer

ArrayBuffer.isView()

isView:是ArrayBuffer的一个静态方法,返回一个布尔值,表示参数是否为ArrayBuffer的视图实例。这个方法大致相当于判断参数,是否为TypedArray实例或DataView实例。

var buffer = new ArrayBuffer(8);
ArrayBuffer.isView(buffer) // false

var v = new Int32Array(buffer);
ArrayBuffer.isView(v) // true

2. TypedArray 视图

TypedArray数组只提供9种固定的构造函数,用来生成相应类型的数组实例。

(1)TypedArray(buffer, byteOffset=0, length?)

视图的构造函数可以接受三个参数:

  • 第一个参数(必需):视图对应的底层ArrayBuffer对象。

  • 第二个参数(可选):视图开始的字节序号,默认从0开始。

  • 第三个参数(可选):视图包含的数据个数,默认直到本段内存区域结束。

// 创建一个8字节的ArrayBuffer
var b = new ArrayBuffer(8);

// 创建一个指向b的Int32视图,开始于字节0,直到缓冲区的末尾
var v1 = new Int32Array(b);

// 创建一个指向b的Uint8视图,开始于字节2,直到缓冲区的末尾
var v2 = new Uint8Array(b, 2);

// 创建一个指向b的Int16视图,开始于字节2,长度为2
var v3 = new Int16Array(b, 2, 2);

v1[0]是一个32位整数,指向字节0~字节3;v2[0]是一个8位无符号整数,指向字节2;v3[0]是一个16位整数,指向字节2~字节3。只要任何一个视图对内存有所修改,就会在另外两个视图上反应出来。

注:byteOffset必须与所要建立的数据类型一致,比如:带符号的16位整数需要两个字节,所以byteOffset参数必须能够被2整除

(2)TypedArray(length)

视图还可以不通过ArrayBuffer对象,直接分配内存而生成。

var f64a = new Float64Array(8); //64字节
f64a[0] = 10;
f64a[1] = 20;
f64a[2] = f64a[0] + f64a[1]; // 30

(3)TypedArray(typedArray)

TypedArray数组的构造函数,可以接受另一个TypedArray实例作为参数。

var typedArray = new Int8Array(new Uint8Array(4));

注:新数组会开辟一段新的内存存数据。

var x = new Int8Array([1, 1]);
var y = new Int8Array(x);
x[0] // 1
y[0] // 1

x[0] = 2;
y[0] // 1

//基于同一段内存
var x = new Int8Array([1, 1]);
var y = new Int8Array(x.buffer);
x[0] // 1
y[0] // 1

x[0] = 2;
y[0] // 2

(4)TypedArray(arrayLikeObject)

//普通数组生成TypedArray实例
var typedArray = new Uint8Array([1, 2, 3, 4]);
//这时TypedArray视图会重新开辟内存,不会在原数组的内存上建立视图


//TypedArray数组转换回普通数组
var normalArray = Array.prototype.slice.call(typedArray);

需要注意的是:TypedArray数组除了没有concat方法之外,拥有普通数组所有的操作方法和属性

如果想要合并多个TypedArray数组,可以用下面这个函数。

function concatenate(resultConstructor, ...arrays) {
  let totalLength = 0;
  for (let arr of arrays) {
    totalLength += arr.length;
  }
  let result = new resultConstructor(totalLength);
  let offset = 0;
  for (let arr of arrays) {
    result.set(arr, offset);
    offset += arr.length;
  }
  return result;
}

concatenate(Uint8Array, Uint8Array.of(1, 2), Uint8Array.of(3, 4))
// Uint8Array [1, 2, 3, 4]

TypedArray数组也可以被遍历。

let ui8 = Uint8Array.of(0, 1, 2);
for (let byte of ui8) {
  console.log(byte);
}
// 0
// 1
// 2

ArrayBuffer 与字符串的互相转换

注:字符串的编码方法是确定的,才可以相互转换。

// ArrayBuffer转为字符串,参数为ArrayBuffer对象
function ab2str(buf) {
  return String.fromCharCode.apply(null, new Uint16Array(buf));
}

// 字符串转为ArrayBuffer对象,参数为字符串
function str2ab(str) {
  var buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
  var bufView = new Uint16Array(buf);
  for (var i = 0, strLen = str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return buf;
}

TypedArray.prototype.buffer:返回整段内存区域对应的ArrayBuffer对象,属性为只读。

TypedArray.prototype.byteLength:返回TypedArray数组占据的内存长度,单位为字节,属性为只读。

TypedArray.prototype.byteOffset:返回TypedArray数组从底层ArrayBuffer对象的哪个字节开始,属性为只读。

TypedArray.prototype.length:TypedArray数组含有多少个成员。

TypedArray.prototype.set():用于复制数组(普通数组或TypedArray数组)。

TypedArray.prototype.subarray():对于TypedArray数组的一部分,再建立一个新的视图。

TypedArray.prototype.slice():返回一个指定位置的新的TypedArray实例。

TypedArray.of():用于将参数转为一个TypedArray实例。

TypedArray.from():返回一个基于这个结构的TypedArray实例。

3. 复合视图

var buffer = new ArrayBuffer(24);

var idView = new Uint32Array(buffer, 0, 1);
var usernameView = new Uint8Array(buffer, 4, 16);
var amountDueView = new Float32Array(buffer, 20, 1);

上面代码将一个24字节长度的ArrayBuffer对象,分成三个部分:

  • 字节0到字节3:1个32位无符号整数

  • 字节4到字节19:16个8位整数

  • 字节20到字节23:1个32位浮点数

4. DataView视图

DataView实例有以下属性,含义与TypedArray实例的同名方法相同。

  • DataView.prototype.buffer:返回对应的ArrayBuffer对象

  • DataView.prototype.byteLength:返回占据的内存字节长度

  • DataView.prototype.byteOffset:返回当前视图从对应的ArrayBuffer对象的哪个字节开始

DataView实例提供8个方法读取内存。

  • getInt8:读取1个字节,返回一个8位整数。

  • getUint8:读取1个字节,返回一个无符号的8位整数。

  • getInt16:读取2个字节,返回一个16位整数。

  • getUint16:读取2个字节,返回一个无符号的16位整数。

  • getInt32:读取4个字节,返回一个32位整数。

  • getUint32:读取4个字节,返回一个无符号的32位整数。

  • getFloat32:读取4个字节,返回一个32位浮点数。

  • getFloat64:读取8个字节,返回一个64位浮点数。

DataView视图提供8个方法写入内存。

  • setInt8:写入1个字节的8位整数。

  • setUint8:写入1个字节的8位无符号整数。

  • setInt16:写入2个字节的16位整数。

  • setUint16:写入2个字节的16位无符号整数。

  • setInt32:写入4个字节的32位整数。

  • setUint32:写入4个字节的32位无符号整数。

  • setFloat32:写入4个字节的32位浮点数。

  • setFloat64:写入8个字节的64位浮点数。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java(十一)数组
数组用来存放相同数据类型的数据,逻辑位置与物理位置都是连续的。数组存放在堆里。栈和堆:栈:方法调用的时候使用栈,局部变量存放在栈里。堆:动态的分配内存,new出来的。引用类型存放在堆里,在栈里存放引用,也就是地址,一般用16进制来表示地址:0x...。基本类型和引用类型的区别:基本类型:在栈中存放的是二进制位。引用
Wesley13 Wesley13
3年前
java文件转二进制
本工具类提供三个方法:1.文件转为二进制数组2.文件转为二进制字符串3.二进制字符串还原为文件可当做工具类直接使用。packagecom.yscredit.sz.util;importorg.springframework.util.FileCopyUtils;
待兔 待兔
4年前
JavaScript中的类型
JavaScript中的类型一、关于类型什么叫做类型?简单地说,类型就是把内存中的一个二进制序列赋予某种意义。比如,二进制序列0100000001110000000101010100101111000110101001111110111110011110如果看作是64位无符号整数类型就是4
Stella981 Stella981
3年前
Redis 基本数据类型
Redis基本数据类型:1.String类型  String是redis最基本的类型,而且string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象。从内部实现来看其实string可以看作byte数组,最大上限是1G字节。下面是string类型的定义。str
Wesley13 Wesley13
3年前
mysql二进制类型
由于之前网站使用第三方登录,QQ昵称比较特殊,所以用二进制的字段类型存储。mysql二进制类型有:BINARYVARBINARYTINYBLOB,BLOB,MEDIUMBLOB,andLONGBLOB顺便列一下各种数据类型的存储范围:StorageRequirementsforNumericTypesDat
Stella981 Stella981
3年前
Linux 磁盘管理之磁盘理论篇
Linux磁盘管理之磁盘理论篇磁盘简介作用:用来存放数据(二进制方式来管理数据)分类机械硬盘固态硬盘机械硬盘组成盘片:上面布满磁性颗粒,保存写入数据主轴:带动盘片转动,转到磁头的下方
Wesley13 Wesley13
3年前
CPU中的二进制数据(整数篇)
1.用二进制数表示计算机信息的原因计算机内部CPU和内存都是IC的一种,它们都有多个引脚。IC的所有引脚,只有直流电压0V或5V两个状态。也就是说,IC的一个引脚,只能表示两个状态。IC的这个特性,决定了计算机的信息数据只能用二进制数来处理。计算机处理信息的最小单位——位,就相当于二进制中的一位。对于用二进制数表示
Wesley13 Wesley13
3年前
Java序列化技术即将被废除!!!
我们的对象并不只是存在内存中,还需要传输网络,或者保存起来下次再加载出来用,所以需要Java序列化技术。Java序列化技术正是将对象转变成一串由二进制字节组成的数组,可以通过将二进制数据保存到磁盘或者传输网络,磁盘或者网络接收者可以在对象的属类的模板上来反序列化类的对象,达到对象持久化的目的。如果你还不熟悉Java序列化技术,请详细阅读《关于Jav
Wesley13 Wesley13
3年前
ES6(六)数值的扩展
二进制和八进制表示法ES6提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)(二进制binary)和0o(或0O)(八进制octonary)表示。0b111110111503//true0o767503//true从ES5开始,在严格模式之中,八进制就不再允许使用前缀0表示,E
Wesley13 Wesley13
3年前
C语言基础之ASCII编码(3)
什么是字符集和字符编码?前面我们已经讲到,计算机是以二进制的形式来存储数据的,它只认识0和1两个数字,我们在屏幕上看到的文字,在存储之前都被转换成了二进制(0和1序列),在显示时也要根据二进制找到对应的字符。可想而知,特定的文字必然对应着固定的二进制,否则在转换时将发生混乱。那么,怎样将文字与二进制对应起来
3A网络 3A网络
2年前
教你如何将二进制文件导入到数据库
教你如何将二进制文件导入到数据库1.1现网业务场景源数据推送二进制流解析二进制解析后的数据导入数据库为了模拟生产的业务场景,客户提供了一个二进制文件及二进制文件的解析程序,需要我们解析二进制文件后导入数据库。1.2测试方案由于客户给出的解析程序是单条解析,为了提升数据导入的性能,需要微批导入的方式,在内存中积攒一定量的数据后,再调用copy