海南什么公司的网站,如何做网站专题,网站添加合适图片,什么网站免费做推广ArrayBuffer对象作为内存区域可以存放多种类型的数据。同一段内存#xff0c;不同数据有不同的解读方式#xff0c;这种解读方式称为“视图#xff08;view#xff09;”。ArrayBuffer有两种类型的视图#xff0c;一种是类型化数组视图#xff08;TypedArray#xff09;…ArrayBuffer对象作为内存区域可以存放多种类型的数据。同一段内存不同数据有不同的解读方式这种解读方式称为“视图view”。ArrayBuffer有两种类型的视图一种是类型化数组视图TypedArray另一种是数据视图DataView。类型化数组视图的数组成员都是同一个数据类型后者的数组成员可以是不同的数据类型。TypedArray视图一共有9种类型每一种视图都是一个构造函数。这些视图实现了数组接口均有length属性都可以使用方括号运算符来获取单个元素所有数组方法都可以在其上面使用。普通数组和TypedArray数组的差异主要在以下方面1、TypedArray数组的所有成员都是同一种类型。2、TypedArray数组的成员是连续的不会有空位不存在稀疏数组的情况。3、TypedArray数组成员的默认值是0。TypedArray数组只是一个视图本身不存储数据它的数据都存储在底层的ArrayBuffer对象中要获取底层对象必须使用buffer属性。TypedArray构造函数TypedArray有四种形式的构造函数分别是1、TypedArray(buffer, byteOffset, length)参数buffer代表了视图底层的ArrayBuffer对象byteOffset表示视图开始的字节序号默认从0开始length代表视图包含的数据个数默认直到本段内存区域结束。其中byteOffset必须是与所要建立的数据类型的字节长度的整数倍否则会出错。var buffer new ArrayBuffer(32);
var i16 new Uint16Array(buffer, 1); // RangeError, Uint16的每个数据的长度为2个字节故byteOffset必须是
2、TypedArray(length)视图可以不通过ArrayBuffer对象直接指定长度分配相应的内存。构造函数的参数代表要分配的成员个数。var i16 new Int16Array(3); // 分配了3*26个字节的内存
i16.buffer.byteLength; // 6
3、TypedArray(typedArray)可以通过一个TypedArray实例来构建另一个TypedArray实例两个实例的类型可以不一样此时新实例只是复制了源实例的值底层的内存是不一样的。var source new Uint16Array(16);
var target new Int16Array(source);
4、TypedArray(arrayLikeObject)可以通过一个类数组对象来创建TypedArray实例数组对象的每一个值就是新实例数组的每一项对应的值。var a new Uint32Array([1,2,3,4]);
a[2]; // 3TypedArray的属性1、TypedArray有一个name属性是用于描述类型数组的字符串值。九个类型数组的name属性分别是Int8Array.name; // Int8Array
Uint8Array.name; // Uint8Array
Uint8ClampedArray.name; // Uint8ClampedArray
Int16Array.name; // Int16Array
Uint16Array.name; // Uint16Array
Int32Array.name; // Int32Array
Uint32Array.name; // Uint32Array
Float32Array.name; // Float32Array
Float64Array.name; // Float64Array
2、BYTES_PER_ELEMENT属性表示这种数据类型的每个元素所占用的字节数。Int8Array.BYTES_PER_ELEMENT; // 1
Uint8Array.BYTES_PER_ELEMENT; // 1
Uint8ClampedArray.BYTES_PER_ELEMENT; // 1
Int16Array.BYTES_PER_ELEMENT; // 2
Uint16Array.BYTES_PER_ELEMENT; // 2
Int32Array.BYTES_PER_ELEMENT; // 4
Uint32Array.BYTES_PER_ELEMENT; // 4
Float32Array.BYTES_PER_ELEMENT; // 4
Float64Array.BYTES_PER_ELEMENT; // 8
3、TypedArray实例的buffer属性返回整段内存区域对于的ArrayBuffer对象。该属性为只读属性。var ab new ArrayBuffer(32);
var ui16 new Uint16Array(ab);
ui16.buffer ab; // true
Object.getOwnPropertyDescriptor(Uint16Array.prototype.__proto__, buffer);
// {get: ƒ, set: undefined, enumerable: false, configurable: true}
4、TypedArray实例的byteLength属性返回TypedArray数组占据的内存长度单位为字节。var ab new ArrayBuffer(32);
var ui16 new Uint16Array(ab, 2);
ui16.byteLength; // 30
5、TypedArray实例的byteOffset属性表示TypedArray数组从底层ArrayBuffer对象的哪个字节开始。var ab new ArrayBuffer(32);
var ui16 new Uint16Array(ab, 2);
ui16.byteOffset; // 2
6、TypedArray实例的length属性表示实例有多少个成员。var ab new ArrayBuffer(32);
var ui16 new Uint16Array(ab, 2);
ui16.length; // 15
TypedArray构造函数的静态方法TypedArray数组的所有构造函数上都有一个静态方法of用于将参数转为一个TypedArray实例。Float32Array.of(12.213, -8, 83.1); // [12.213, -8, 83.1]
// 也可以用下面的方法新建同样的数组
var a new Float32Array([12.213, -8, 83.1]);
var b new Float32Array(3);
b[0] 12.213;
b[1] -8;
b[2] 83.1
TypedArray数组的另一个静态方法from()接受一个可遍历的数据结构比如数组作为参数返回一个基于此结构的TypedArray实例。同时还可以接受第二个函数参数在新建实例时对每一个元素向映射到函数中将函数的结果作为新实例的值。Uint16Array.from([1,2,3]); // [1,2,3]
Uint16Array.from([1,2,3], value value * 2); // [2,4,6]
TypedArray原型对象上的方法由于TypedArray实现了数组接口故可以在TypedArray上使用数组的方法来进行操作。Object.getOwnPropertyNames(Uint16Array.prototype.__proto__);
/* [
constructor,
buffer,
byteLength,
byteOffset,
length,
entries,
keys,
values,
copyWithin,
subarray,
set,
every,
fill,
filter,
find,
findIndex,
includes,
indexOf,
join,
lastIndexOf,
forEach,
map,
reduce,
reduceRight,
reverse,
slice, some,
sort,
toLocaleString,
toString] */
1、TypedArray.prototype.copyWithin(target, start[, end this.length])从原数组的start位置开始复制数据到end不含填充到target及以后的位置上并返回修改后的数组。var array new Int16Array(10);
array.set([1,2,3]);
array; // [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]
array.copyWithin(3, 0, 3);
array; // [1, 2, 3, 1, 2, 3, 0, 0, 0, 0]
2、TypedArray.prototype.entries()返回TypedArray的键值对遍历器var array new Int16Array(3);
array.set([1,2,3]);
var iter array.entries();
for (let element of iter) {console.log(element);
}
/*
[0,1]
[1,2]
[2,3]
*/
3、TypedArray.prototype.every(callback[, thisArg])对数组的每一个元素都指向一次函数操作如果每个元素都能通过测试则返回true否则返回false。var array new Int16Array(3);
array.set([1,2,3]);
array.every(function (value) { return value % 2 1; }); // false 2不是奇数
4、TypedArray.prototype.fill(value[, start 0[, end this.length]])使用指定值填充TypedArray从start到end不含的全部元素。new Uint8Array([1, 2, 3]).fill(4); // Uint8Array [4, 4, 4]
new Uint8Array([1, 2, 3]).fill(4, 1); // Uint8Array [1, 4, 4]
new Uint8Array([1, 2, 3]).fill(4, 1, 2); // Uint8Array [1, 4, 3]
new Uint8Array([1, 2, 3]).fill(4, 1, 1); // Uint8Array [1, 2, 3]
new Uint8Array([1, 2, 3]).fill(4, -3, -2); // Uint8Array [4, 2, 3]
5、TypedArray.prototype.filter(callback[, thisArg])对每个数组元素进行测试保留通过测试函数的值。function isBigEnough(element, index, array) {return element 10;
}
new Uint8Array([12, 5, 8, 130, 44]).filter(isBigEnough);
// Uint8Array [ 12, 130, 44 ]
6、TypedArray.prototype.find(callback[, thisArg])返回第一个通过测试函数的值。如果没有一个元素通过测试则返回undefined。function isPrime(element, index, array) {var start 2;while (start Math.sqrt(element)) {if (element % start 1) {return false;}}return element 1;
}var uint8 new Uint8Array([4, 5, 8, 12]);
console.log(uint8.find(isPrime)); // 5
7、TypedArray.prototype.findIndex(callback[, thisArg])返回第一个通过测试函数的值的下标。如果没有一个元素通过测试则返回undefined。function isPrime(element, index, array) {var start 2;while (start Math.sqrt(element)) {if (element % start 1) {return false;}}return element 1;
}var uint16 new Uint16Array([4, 5, 8, 12]);
console.log(uint16.findIndex(isPrime)); // 1
8、TypedArray.prototype.forEach(callback[, thisArg])为每一个数组元素执行指定的函数。function logArrayElements(element, index, array) {console.log(a[ index ] element);
}new Uint8Array([0, 1, 2, 3]).forEach(logArrayElements);
/*
a[0] 0
a[1] 1
a[2] 2
a[3] 3
*/
9、TypedArray.prototype.includes(searchElement[, fromIndex])返回一个布尔值表明数组中从下标fromIndex开始到结尾是否包含了指定的搜索元素。var uint8 new Uint8Array([1,2,3]);
uint8.includes(2); // true
uint8.includes(4); // false
uint8.includes(3, 3); // false// NaN 的处理 仅仅对 Float32 和 Float64 为 true
new Uint8Array([NaN]).includes(NaN); // false, 因为 NaN 传递给构造器时转换为 0
new Float32Array([NaN]).includes(NaN); // true;
new Float64Array([NaN]).includes(NaN); // true;
10、TypedArray.prototype.indexOf(searchElement[, fromIndex 0])在TypedArray中搜索元素返回第一次出现的位置下标如果找不到对应的元素则返回-1。let uint8 new Uint8Array([2, 5, 9]);
uint8.indexOf(2); // 0
uint8.indexOf(7); // -1
uint8.indexOf(9, 2); // 2
uint8.indexOf(2, -1); // -1
uint8.indexOf(2, -3); // 0
11、TypedArray.prototype.join([separator ,])将数值各个元素转为字符串再使用separator将其各个字符串连接后返回。var array new Int16Array([1,2,3,4]);
var str array.join(-);
str; // 1-2-3-4
12、TypedArray.prototype.keys()返回一个数组下标的遍历器。var array new Int16Array(3);
array.set([1,2,3]);
var iter array.keys();
for (let index of iter) {console.log(index);
}
/*
0
1
2
*/
13、TypedArray.prototype.lastIndexOf(searchElement[, fromIndex typedarray.length])在TypedArray中搜索元素返回最后一次出现的位置下标如果找不到对应的元素则返回-1。const uint8 new Uint8Array([2, 5, 9, 4, 5, 3]);
uint8.lastIndexOf(5); // 4
14、TypedArray.prototype.map(callback[, thisArg])map方法对类型化数组中的元素调用提供的 callback函数按照顺序并且会从结果构造新的类型化数组。const uint8 new Uint8Array([2, 5, 9, 4, 5, 3]);
const new_ui8 uint8.map(function (value) {return value * 2;
});
new_ui8; // [4,10,18,8,10,6]
15、TypedArray.prototype.reduce(callback[, initialValue])reduce() 方法接受一个函数作为参数这个函数作为一个累加器从左到右遍历整个类型数组最后返回一个单一的值。const uint8 new Uint8Array([2, 5, 9, 4, 5, 3]);
uint8.reduce(function (a, b) {return a b;
}, 0); // 28
16、TypedArray.prototype.reduceRight(callback[, initialValue])reduceRight()在累加器和类型化数组的每个元素上从右到左调用函数使其归约为单一的值。const uint8 new Uint8Array([2, 5, 9, 4, 5, 3]);
uint8.reduceRight(function (a, b) {return a b;
}); // 28
17、TypedArray.prototype.reverse()原地逆序TypedArray数组。const uint8 new Uint8Array([2, 5, 9, 4, 5, 3]);
uint8.reverse(); // [3,5,4,9,5,2]
18、TypedArray.prototype.set(array [,offset])set()方法用于从指定数组中读取值并将其存储在类型化数组中。var buffer new ArrayBuffer(8);
var uint8 new Uint8Array(buffer);
uint8.set([1,2,3], 3);
console.log(uint8); // Uint8Array [ 0, 0, 0, 1, 2, 3, 0, 0 ]
19、TypedArray.prototype.slice([begin[, end]])返回一个指定位置的新的TypedArray实例。const uint8 new Uint8Array([2, 5, 9, 4, 5, 3]);
uint8.slice(2,5); // [9,4,5]
20、TypedArray.prototype.some(callback[, thisArg]) 提供一个测试函数当TypedArray中的某一个元素通过测试函数则返回true。const uint8 new Uint8Array([2, 5, 9, 4, 5, 3]);
uint8.some(function (value) { return value 5; }); // true21、TypedArray.prototype.sort([compareFunction])sort()方法原地排序类型化数组的元素并且返回类型化数组。这个方法的算法和Array.prototype.sort()相同。 var numbers new Uint8Array([40, 1, 5, 200]);
numbers.sort();
// Uint8Array [ 1, 5, 40, 200 ]
// 在这里按数值排序数值时
// 不需要比较函数。
22、TypedArray.prototype.subarray([begin [,end]])对TypedArray数组的一部分再建立一个新的视图。第一个参数是起始的成员序号第二个参数是结束的成员序号不含该成员如果省略则包含剩余的全部成员。新视图和源视图底层的ArrayBuffer是共用的。const uint8 new Uint8Array([2, 5, 9, 4, 5, 3]);
const new_uint8 uint8.subarray(2, 5); // [9,4,5]
new_uint8[1] 10;
new_uint8; // [9,10,5]
uint8; // [2,5,9,10,5,3]
23、TypedArray.prototype.toLocaleString()toLocaleString()方法返回一个字符串表明该类型化数组的元素。这些元素被转化为字符串并由一个区域设置指定的分隔符例如逗号 “,”分隔。这个方法与Array.prototype.toLocaleString()拥有相同的算法。同时由于类型化数组的元素都是数将每个元素转化为字符串的算法与Number.prototype.toLocaleString()是相同的。var uint new Uint32Array([2000, 500, 8123, 12, 4212]);
uint.toLocaleString(ja-JP, { style: currency, currency: JPY });
// 2,000,500,8,123,12,4,212
24、TypedArray.prototype.toString()TypedArray 对象重写了Object的 toString方法。对 TypedArray 对象来说toString 方法联结了数组并返回一个字符串它包含由逗号分隔的数组元素。var numbers new Uint8Array([2, 5, 8, 1, 4])
numbers.toString(); // 2,5,8,1,4
25、TypedArray.prototype.values()返回TypedArray的键值遍历器。const uint8 new Uint8Array([2, 5, 9, 4, 5, 3]);
var iter uint8.values();
for (let ele of iter) {console.log(ele);
}
/*
2
5
9
4
5
3
*/
26、TypedArray.prototype[iterator]()返回TypedArray键值对的遍历器效果和values()方法一样。const uint8 new Uint8Array([2, 5, 9, 4, 5, 3]);
var iter uint8[Symbol.iterator]();
for (let ele of iter) {console.log(ele);
}
/*
2
5
9
4
5
3
*/
TypedArray的字节序字节序是指数值在内存中的表示方式。var buffer new ArrayBuffer(16);
var int32View new Int32Array(buffer);
for (let i 0; i int32View.length; i) {int32View[i] i * 2;
}
int32View; // [0,2,4,6]
上述代码新建了一个16字节的内存区域并在其上建了一个32位4字节的视图该视图有4个元素对元素分别赋值为0246。如果对该内存区域上新建一个16位2字节的视图我们可以看出数据的存储方式。var int16View new Int16Array(buffer);
for (let value of int16View) {console.log(value);
}
/*
0
0
2
0
4
0
6
0
*/
用图来说明如下由于x86体系的计算机都采用小端字节序相对重要的字节排在后面的内存地址相对不重要的字节排在前面的内存地址。比如一个占据4字节的十六进制数0x12345678决定其大小的最重要的字节是“12”最不重要的是“78”故在内存中存储顺序是“78563412”。TypedArray数组内部也采用的是本机操作系统设定的字节序读写数据。TypedArray对溢出的处理不同的视图类型所能容纳的数值范围是确定的超出这个范围就会出现溢出。TypedArray数组对于溢出采用的处理方法是求余值。正向溢出的含义是指输入值大于可容纳的当前数据类型的最大值最后得到的值等于当前数据类型的最小值加上余值再减去1。负向溢出等于当前数据类型的最大值减去余值再加上1。// 无符号单字节整型可容纳的最大数值是255最小数值是0
var uint8 new Uint8Array(1);
uint8[0] 256; // 正向溢出超出最大值范围余值是1
uint8[0]; // 0 最小值余值-10uint8[0] -12; // 负向溢出超出最小值范围余值是12
uint8[0]; // 最大值-余值1255-121244
UInt8ClampedArray视图的溢出与其他8种类型的规则有所不同。负向溢出的值都是0正向溢出的值都是255。var a new Uint8ClampedArray(1);
a[0] 2112;
a[0]; // 255
a[0] -123
a[0]; // 0
利用TypedArray构建复合视图由于视图的构造函数可以指定起始位置和长度所以在同一段内存中可以依次存放不同类型的数据这就叫复合视图。var ab new ArrayBuffer(24);
var idView new Uint32Array(buffer, 0, 1);
var userNameView new Uint8Array(buffer, 4, 16);
var amountView new Float32Array(buffer, 20, 1);
上面的代码将一个24字节的内存分成3个部分字节0到字节3,1个32位无符号整数用于存放ID。字节4到字节19存放16个8位无符号整数。剩下4个字节存放1个32位浮点数。这样数据接口用C语言描述如下struct User {unsigned int id;char[16] username;float amount;
};同系列文章《JavaScript二进制数组1ArrayBuffer》《JavaScript二进制数组2TypedArray视图》《JavaScript二进制数组3DataView视图》