JavaScript ArrayBuffer类型数组

ArrayBuffer这东西啊,说白了就是一块内存。
固定大小,不能变。
它自己啥也不干,就是个容器。
得靠别人看,靠别人解释。

先看块内存咋整。
比如new ArrayBuffer(1 6 )。
这表示你跟浏览器说,我要1 6 个字节的内存。
浏览器就给你分配一块,大小正好1 6 这块内存里面啥也没有,就是0。

ArrayBuffer有个属性叫byteLength。
这表示这块内存有多大。
比如console.log(buffer.byteLength),输出1 6 ,说明你确实要了1 6 个字节。

真正操作这块内存,得靠视图。
主要有两种,TypedArray和DataView。

先说TypedArray。
这玩意儿按类型看内存。
比如Uint8 Array,8 位无符号整数。
意思就是这块内存里的每个字节,都当个无符号整数看。

看个例子。
let buffer = new ArrayBuffer(8 );。
分配了8 个字节。
然后let view = new Uint8 Array(buffer);。
这意思就是,把这8 个字节,按Uint8 Array的方式看。

现在你可以操作view[0] = 4 2 ;。
这表示把第1 个字节(从0开始数)设为4 2 Uint8 Array里,4 2 就是二进制的001 01 01 0
console.log(view[0]);。
输出4 2 没错,这就是你刚才设定的值。

再比如Int1 6 Array,1 6 位有符号整数。
一个字节看两个,一个字节看两个,总共8 个字节,能看4 个1 6 位的数。

还有Float3 2 Array、Float6 4 Array,分别对应3 2 位和6 4 位浮点数。
看内存的方式不一样,解释出来的值也不一样。

重点来了,一个ArrayBuffer可以搞多个视图。
同一个内存块,不同人用不同方式看,看到的可能不一样。

比如let buffer = new ArrayBuffer(8 );。
然后let int3 2 View = new Int3 2 Array(buffer);。
这表示把8 个字节,按3 2 位整数看。
8 个字节能看2 个3 2 位的。

再let int8 View = new Int8 Array(buffer);。
这表示把8 个字节,按8 位整数看。
8 个字节能看8 个8 位的。

现在int3 2 View[0] = 0x1 2 3 4 5 6 7 8 ;。
这表示把第1 个3 2 位(4 个字节)设为0x1 2 3 4 5 6 7 8
注意字节序。
在电脑里,小端序是低地址存低字节。
所以0x1 2 3 4 5 6 7 8 ,在内存里是这样放的:
7 8 5 6 3 4 1 2 第一个字节是7 8
所以int8 View[0]就是7 8 int8 View[1 ]是5 6 ,以此类推。

DataView更灵活。
它可以指定偏移量和字节序。
适合处理不同平台的二进制协议。

比如let buffer = new ArrayBuffer(8 );。
然后let dataView = new DataView(buffer);。

dataView.setInt3 2 (0, 0x1 2 3 4 5 6 7 8 , true);。
这表示从偏移量0开始,写入3 2 位整数0x1 2 3 4 5 6 7 8 true表示小端序。

dataView.setFloat3 2 (4 , 3 .1 4 , false);。
这表示从偏移量4 开始,写入3 2 位浮点数3 .1 4 false表示大端序。

后来你可以用getInt3 2 (0, true)读取。
getInt3 2 (0, true)就是0x1 2 3 4 5 6 7 8 用getFloat3 2 (4 , false)读取,就是3 .1 4
ArrayBuffer在实际中用得多。
比如网络通信。
你跟服务器传数据,可能用WebSocket。
WebSocket传输的就是二进制。
你就用ArrayBuffer来打包数据。

文件操作也用。
比如用FileReader读文件,FileReader.result就是ArrayBuffer。
你拿到这个ArrayBuffer,再用TypedArray或DataView处理。

WebGL也用。
你传顶点数据、纹理数据,都得用ArrayBuffer。
浏览器渲染速度快,但前提是你得给它高效的数据。

音视频处理也一样。
比如操作音频流,视频帧,都是直接操作原始的二进制数据。
ArrayBuffer就是干这个的。

总之ArrayBuffer就是个内存块。
得靠视图才能用。
TypedArray简单直接,DataView灵活。
用好了,处理二进制数据效率高。

不同类型的变量在内存中占用相同大小的空间

说白了,变量在内存里占多大空间完全看它是什么类型,这话没错。
先说最重要的,基本类型差异最明显——比如char固定1 字节存字符,int常见4 字节存整数,但去年我们跑的那个3 2 位Linux项目里,int居然只占2 字节,直接把代码干崩了;另外一点,复合类型像数组是单个元素乘数量,结构体会因为内存对齐多占点空间,比如4 字节对齐,当个4 字节补丁啥的。
还有个细节挺关键的,动态类型语言比如Python,int小的时候可能用4 字节,一变大直接爆成几千字节,用行话说叫雪崩效应,其实就是前面一个小延迟把后面全拖垮了。

我一开始也以为Java int永远4 字节,后来发现不对,Java虚拟机统一管理,但具体还是看系统。
等等,还有个事,浮点数精度和空间绑一块儿,双精度double占8 字节,比float精度高,但计算慢一丢丢,这个点很多人没注意。
建议写代码时别瞎猜内存大小,查查官方文档或者用工具测一下。

javascript中数字占多少位bit

等等,我昨天调试代码时遇到个怪事。
有个循环累加的小函数,跑了几万次结果突然不对了,最后发现是累加了一个特别小的数,比如0.1 +0.2 这种。
这种小数在JS里特别魔幻,你知道为啥吗?

数据类型有哪几种

数据类型就是编程里用来告诉电脑,这变量装的是什么货。
关键看内存分配快不快,操作安不安全。

基础类型直接存数值,比如int、float,简单快捷。

参考类型是存地址,比如string,内存用得灵活。

复合类型像tuple,记录单元,能组合不同类型。

抽象高级类型比如栈、队列,函数类型,更复杂。

特殊类型variant,灵活但效率低。

关键是要优化内存,保证操作安全,代码看着也顺眼。

选数据类型,得看你要啥平衡性能和灵活度。