Open FrankKai opened 4 years ago
扩展: 1.什么是Web IDL type interface definition language,用来描述打算在web浏览器中实现的interface。
new DataView(buffer [, byteOffset [, byteLength]])
,buffer是ArrayBuffer实例,byteOffset是新DataView的偏移量,byteLength是新DataView的字节长度。view.setInt16(1, 32767); // (max signed 16-bit integer)
,值。
// create an ArrayBuffer with a size in bytes
var buffer = new ArrayBuffer(16);
// Create a couple of views
var view1 = new DataView(buffer);
var view2 = new DataView(buffer,12,4); //from byte 12 for the next 4 bytes
view1.setInt8(12, 42); // put 42 in slot 12
console.log(view1.buffer);
console.log(view2.buffer);
console.log(view1.getInt8(12));
console.log(view2.getInt8(0));
new DataView(buffer).setInt16(0, 256, true)
怎么理解?
true是littleEndian,也就是小端模式,低位数据存储在低地址,Int16Array uses the platform's endianness。
扩展: 1.什么是Endianness 内存存储的大小端模式。 所谓大端模式,指的是低位数据高地址,0x12345678,12存buf[0],78(低位数据)存buf[3](高地址)。也就是常规的正序存储。 小端模式与大端模式相反。0x12345678,78存在buf[0],存在低地址。
使用了typed array的web api有以下这些。
blob.arrayBuffer().then(buffer => /* 处理ArrayBuffer */)
XMLHttpRequest.prototype.send()
支持发送typed arrays 和ArrayBuffer对象作为入参
XMLHttpRequest.send(body) body支持多种数据body。Document(序列化的);BodyInit:包括Blob,BufferSource,FormData,URLSearchParams,ReadableStream或者USVString object。规范中写明了其算法:https://fetch.spec.whatwg.org/#bodyinit。其中有一步是设置对象类型,切换Content-Type为对象的MIME类型。
IDL的定义如下:
interface mixin Body {
readonly attribute ReadableStream? body;
readonly attribute boolean bodyUsed;
[NewObject] Promise<ArrayBuffer> arrayBuffer();
[NewObject] Promise<Blob> blob();
[NewObject] Promise<FormData> formData();
[NewObject] Promise<any> json();
[NewObject] Promise<USVString> text();
};
通过send方法发送二进制数据的最好方式是:ArrayBufferView或Blob。
拓展:interface mixin Body{}怎么理解? 引出一个很有趣的东西。interCaps。
Rule: Use interCaps for naming. All methods and attributes should begin with a lowercase letter. Every subsequent word in the method or attribute name should be capitalized. Avoid capitalizing first letters and using underscores to separate words. Why: IDL usually follows Java and JavaScript convention, which is intercaps. In addition, the first letter of all names are promoted to upper case in C++. The C++ signature is the same whether or not the first letter is capitalized.
IDL通常用js或者java实现。此处的interface mixin是java实现。
处理完typed array以后,很多情况下会将其转换为普通数组。 可以使用Array.from做转换。或者使用以下代码转换。
let typedArray = new Uint8Array([1, 2, 3, 4]);
let normalArray = Array.from(typedArray);
let typedArray = new Uint8Array([1, 2, 3, 4]),
normalArray = Array.prototype.slice.call(typedArray);
normalArray.length === 4;
normalArray.constructor === Array;
// 创建一个16字节定长的buffer
let buffer = new ArrayBuffer(16);
此处会用到通信原理中学到的:1byte = 8bit。(1个字节等于8个比特)
上图中的Int8,Int16,Int32,Uint8中的数字都是以bit为单位的。
其总空间为16*8 = 128bit。
因此Int8Array和Uint8Array类型的ArrayBuffer长度为16。
因此Int16Array类型的ArrayBuffer长度为8。
因此Int32Array类型的ArrayBuffer长度为4。
位数越大,说明ArrayBuffer中的一个0占用的内存空间越大。
// 此时对于一块初始字节数是0的内存,在这块内存上可以为所欲为
// 通过byteLength属性,可以获得一个buffer占用的字节内存空间
console.log(buffer.byteLength); // 16(bytes)
// 此时buffer是无法作用的,我们需要创建一个view
// 以下代码会创建一个将buffer中的数据转换为32-bit的有符号整型数组
let int32View = new Int32Array(buffer);
这里除了可以创建Int32Array的ArrayBufferView,还可以创建Int8Array,Uint8Array,Int16Array等等类型的ArrayBufferView。
// 可以像普通数组一样去遍历ArrayBufferView数组
int32View.forEach((e,i,arr)=>{ arr[i] = i; })// 0,1,2,3
这个数组有4个entry,每个entry占用4个byte(字节),所以总计16个字节。
struct someStruct {
unsigned long id; // long 32bit
char username[16];// char 8bit
float amountDue;// float 32bit
};
上面的C结构在js中可以这样定义:
let buffer = new ArrayBuffer(24);
// ... read the data into the buffer ...
let idView = new Uint32Array(buffer, 0, 1);
let usernameView = new Uint8Array(buffer, 4, 16);
let amountDueView = new Float32Array(buffer, 20, 1);
偏移量为什么是1,4,20? 因为32/8 = 4。0到3属于idView。 8/8 =1。4到19属于usernameView。 32/8 = 4。20到23属于amountView。
需要注意C语言的数据结构是与平台对齐的。因此C语言中的long,char,float具体占用多少bit,与平台有关。
1.Uint32Array(buffer, 0, 1)
其中的0,1代表什么?
buffer:ArrayBuffer constructor。构造时固定。只读。
byteOffset:0代表从ArrayBuffer开始start位置的offset。构造时固定。只读。
length:ArrayBuffer中元素的个数。构造时固定。只读。
byteLength: ArrayBuffer占用空间的大小。构造时固定。只读。
2.length与byteLength区别是什么?
var buffer = new ArrayBuffer(16);
var int32View = new Int32Array(buffer);
int32View.length; // 4
int32View.byteLength; // 16
主要参考这篇文章:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays