JavaScript中的缓冲数组和强类型数组
在做最近的几个demo的时候碰到了ArrayBuffer(缓冲数组)的这样一个东西,所以在此整理一下相关的知识点。
1.什么是ArrayBuffer
你可以把ArrayBuffer当做一个内存的容器,以下代码声明了1kb的内存空间,但是你不可以直接通过数组下标获取的里面的数据。
//声明1kb的内存空间
var buffer = new ArrayBuffer(1024);
console.log(buffer[0]) //..undefined
2.Javascript的强类型数组
强类型数组有三种基本类型:
- Int 整数
- Uint 无符号整数
- Float IEEE754浮点数
根据这些类型MDN给出了JavaScript的以下几个API:
- Int8Array
- Uint8Array
- Uint8ClampedArray
- Int16Array
- Uint16Array
- Int32Array
- Uint32Array
- Float32Array
- Float64Array
基本使用
//创建一个有3个元素的8bit无符号整型
var a=new Uint8Array(3);
var b = new Uint8Array([1,2,3]);
//假如输入一个非数字呢
var c = new Uint8Array([258,1.3,-23,"hello"]);
console.log(a); // Uint8Array(3) [0,0,0,buffer...]
console.log(b); // Uint8Array(3) [1,2,3,buffer...]
console.log(c); // Uint8Array(3) [2,1,233,0,buffer...]
诶,我们可以发现在输入258的时候,范围溢出了uint8的0~255位,输入值就变成了258-255 = 2 了。浮点型直接去了尾数,-23二进制是11101001即得233 ,字符串型变成了0。
2.通过强类型数组来使用ArrayBuffer
var buffer=new ArrayBuffer(2);
var a=new Uint8Array(buffer);
var b=new Int8Array(buffer);
a[0]=100;
a[1]=255;
console.log(a); // Uint8Array(2) [100,255]
console.log(b); //Int8Array(2) [100, -1]
我们发现Int8类型在输入255的时候,溢出了–128 到 127的范围,输入值就变成了-128+255-128 = -1 了。
假如你只学过脚本语言(Python,JavaScript)对数据类型字节数(多少bit位来表达一个数)和范围还没有了解的同学,建议点击链接:TypedArray(MDN),或者随便找一个C/C++的数据类型看一下。
3.Uint8ClampedArray和Uint8Array的区别
就拿上例来说:
var c = new Uint8Array([258,1.3,-23,"hello"]);
console.log(c); // Uint8Array(3) [2,1,233,0,buffer...]
var d = new Uint8ClampedArray([258,1.3,-23,"hello"]);
console.log(d); // Uint8ClampedArray(3) [255,1,0,0,buffer...]
在处理溢出的时候,Uint8ClampedArray将超出255的值归到了255,将负数值全部归为了0。
4.实例分析
一、使用Canvas读取图片像素信息的实例:
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var image = new Image();
image.src = 'test.jpg';
image.onload = function() {
context.drawImage(image, 0, 0, this.width, this.height);
imageData = context.getImageData(0, 0, this.width, this.height).data;
console.log(imageData); //Uint8ClampedArray(1048576) [2, 2, 14, 255, 2, 2, …]
}
可以见得,canvas的api为了提高读取效率也使用了Uint8ClampedArray
二、读取音频高低数据(用作音频可视化)的实例:
var url = "http://localhost/test.mp3"
var xhr = new XMLHttpRequest();
var AudioContext = new AudioContext();
xhr.open("GET", url);
xhr.responseType = "arraybuffer";
xhr.onload = function(data){
musicData = data.target.response;
musicData = AudioContext.decodeAudioData(musicData,function(buffer){
var analyser = AudioContext.createAnalyser(buffer);
var arr = new Uint8Array(analyser.frequencyBinCount);
var bufferSource = AudioContext.createBufferSource();
bufferSource.connect(analyser);
analyser.connect(AudioContext.destination);
bufferSource.buffer = buffer;
bufferSource.start();
function v(){
//analyser.getByteFrequencyData 要求传入一个Uint8Array,并且我们让它不断的更新
audio = analyser.getByteFrequencyData(arr);
console.log(arr);
requestAnimationFrame(v);
}
requestAnimationFrame(v);
});
}
xhr.send();
上传一张结果图:
三、使用二进制数据加密前端资源文件url链接:
<body>
<audio id="audio" controls></audio>
</body>
<script type="text/javascript">
var url = "http://localhost/test.mp3"
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = "arraybuffer";
xhr.onload = function(){
var arrayBuffer = new Uint8Array(this.response);
// 把资源文件转成blob用用户不可以直接下载使用的格式来转化,起到加密的作用
var blob = new Blob([arrayBuffer], {type: 'mine'});
var url = window.URL.createObjectURL(blob);
document.getElementById('audio').src = url;
console.log(url);
}
xhr.send();
</script>
上传一张结果图:
四、bitmap(位图)
问题:访客统计问题,10万个访客需要验证是它否存在也许用数组就可以容易实现了,那么当你有50亿个访客的时候呢。
这是一个后端常见的访客统计问题,当然,JavaScript也可以实现bitmap啦。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>bitmap</title>
</head>
<body>
<input type="text" placeholder="input a number" id="number">
<button id="set">添加</button>
<button id="isset">验证是否存在</button>
<button id="reset">删除</button>
<p id="answer"></p>
</body>
<script>
function Bitmap(bytes){
// >> 5 相当于 bytes / 32
// 10000000 / 32 * 4 / 1024 / 1024 约等于 12.5 MB
var buffer = new ArrayBuffer(bytes >> 5 + 1)
this.map = new Uint32Array(buffer)
}
Bitmap.prototype.set = function(num){
let ind = num >> 5;
let pos = num % 32;
this.map[ind] |= (1 << pos);
}
Bitmap.prototype.isSet = function(num){
let ind = num >> 5;
let pos = num % 32;
let flag = false;
if (this.map[ind] & (1 << pos)) flag = true;
return flag;
}
Bitmap.prototype.reSet = function(num){
let ind = num >> 5;
let pos = num % 32;
this.map[ind] &= ~(1 << pos)
}
var bitmap = new Bitmap(100000000)
document.getElementById("set").onclick = function(){
let num = document.getElementById("number").value;
bitmap.set(num)
}
document.getElementById("isset").onclick = function(){
let num = document.getElementById("number").value;
document.getElementById("answer").innerText = bitmap.isSet(num)
}
document.getElementById("reset").onclick = function(){
let num = document.getElementById("number").value;
bitmap.reSet(num)
}
</script>
</html>
使用keras-js实现前端预测手写字母
*注意,以下代码是不完整的,github有全套代码。
export default {
name: 'keras-js',
data () {
return {
input: new Float32Array(784),
output: new Float32Array(10),
outputClasses: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
}
上传一张结果图:
总结:
Javascript的强类型数组和Arraybuffer一般用于要调用底层api进行数据处理的一些操作,意义在于平时使用的Array对象说它是数组,其实是一个从哈希表扩展的结构体。因此它可以提供push、splice等一些列操作。这就意味着他们的效率是很低的。Canvas,WebGL的api又需要直接访问内存,这时候强类型数组(兼容IE10)出现了,被用于专门处理这一块的数据。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?