当前位置: 首页 > article >正文

解锁二进制数组:JS、TS、ArkTS 解析

二进制数组基础入门

在编程的世界里,二进制数组就像是一把隐藏的钥匙,虽然不常被提及,但却在许多关键领域发挥着至关重要的作用。从计算机的底层硬件到前端的高性能计算,二进制数组都有着广泛的应用。

在计算机科学中,二进制是数据存储和处理的基础。二进制数组则是一种特殊的数据结构,它允许我们以数组的形式直接操作二进制数据。这在处理大量数据时,能够大大提高效率和性能。比如在 WebGL 中,二进制数组用于向 GPU 传输顶点数据,使得图形渲染更加流畅;在音频处理中,它可以高效地访问和处理音频样本数据;在网络通信中,二进制数组能够实现更快速的数据传输。

对于 JavaScript、TypeScript 和 ArkTS 开发者来说,掌握二进制数组的使用,不仅能够提升我们对语言底层的理解,还能让我们在处理复杂数据时更加得心应手。无论是优化代码性能,还是实现一些高级功能,二进制数组都能成为我们的得力助手。接下来,让我们一起深入探索二进制数组的奥秘,看看它在这三种语言中是如何发挥作用的。

JS 中的二进制数组

(一)ArrayBuffer:内存基石

在 JavaScript 中,ArrayBuffer对象代表内存中一段固定长度的二进制数据缓冲区。它就像是一块原始的内存空间,为存储二进制数据提供了基础。你可以把它想象成一个仓库,里面存放着各种二进制数据,但这个仓库本身并没有提供直接操作这些数据的方法。

ArrayBuffer的构造函数允许我们分配指定字节大小的内存区域。例如,const buffer = new ArrayBuffer(16); 这行代码创建了一个大小为 16 字节的ArrayBuffer,就像是开辟了一个 16 平方米的仓库空间,每个字节的初始值都为 0。

ArrayBuffer有一些重要的属性,比如byteLength属性,它返回ArrayBuffer所占据的内存字节长度。在上面的例子中,buffer.byteLength 的值就是 16。虽然ArrayBuffer不能直接读写数据,但它提供了slice方法,用于创建一个新的ArrayBuffer,其内容是原ArrayBuffer中指定字节范围的副本。比如,const newBuffer = buffer.slice(0, 8); 会创建一个新的ArrayBuffer,包含原buffer前 8 个字节的数据。

(二)TypedArray 视图:数据解析利器

TypedArray并不是一个单一的构造函数,而是一组构造函数,它为ArrayBuffer提供了一种视图,让我们可以以特定的数据类型来解读和操作ArrayBuffer中的数据。就好比给仓库里的货物贴上了不同的标签,告诉我们如何去理解和使用这些货物。

TypedArray一共有 9 种不同的视图类型,每种类型都对应一种特定的数据类型和字节长度。例如:

  • Int8Array:8 位有符号整数,每个元素占 1 个字节,取值范围是 -128 到 127。
  • Uint8Array:8 位无符号整数,每个元素占 1 个字节,取值范围是 0 到 255。
  • Int16Array:16 位有符号整数,每个元素占 2 个字节,取值范围是 -32768 到 32767。
  • Uint16Array:16 位无符号整数,每个元素占 2 个字节,取值范围是 0 到 65535。
  • Int32Array:32 位有符号整数,每个元素占 4 个字节,取值范围是 -2147483648 到 2147483647。
  • Uint32Array:32 位无符号整数,每个元素占 4 个字节,取值范围是 0 到 4294967295。
  • Float32Array:32 位浮点数,每个元素占 4 个字节,用于表示小数。
  • Float64Array:64 位浮点数,每个元素占 8 个字节,能表示更大范围和更高精度的小数。
  • Uint8ClampedArray:8 位无符号整数,每个元素占 1 个字节,与Uint8Array不同的是,它在处理溢出时会将值钳制在 0 到 255 之间 。

TypedArray的构造函数有多种用法。我们可以通过已有的ArrayBuffer来创建,比如:

const buffer = new ArrayBuffer(8);
const int8Array = new Int8Array(buffer);

这里创建了一个基于buffer的Int8Array视图,这样就可以通过int8Array来操作buffer中的数据了。

也可以直接指定长度来创建,此时会自动分配一个对应的ArrayBuffer:

const uint16Array = new Uint16Array(4);

这行代码创建了一个长度为 4 的Uint16Array,底层会分配一个大小为 8 字节(因为每个Uint16Array元素占 2 个字节)的ArrayBuffer。

还可以通过其他TypedArray实例或类数组对象来创建:

const sourceArray = new Uint8Array([1, 2, 3, 4]);
const targetArray = new Int16Array(sourceArray);

const arrayLike = [10, 20, 30];
const newArray = new Uint32Array(arrayLike);

TypedArray和普通数组在一些方面存在差异。普通数组的元素类型可以是任意的 JavaScript 值,而TypedArray的所有成员都是同一种类型。TypedArray的成员在内存中是连续存储的,不会有空位,而普通数组可能存在稀疏的情况。此外,TypedArray数组成员的默认值是 0,普通数组则没有这样的默认值设定。

TypedArray还具有一些特有属性,比如BYTES_PER_ELEMENT属性表示每个元素所占用的字节数,buffer属性返回其底层的ArrayBuffer对象,byteLength属性返回视图占据的内存长度,byteOffset属性表示视图从底层ArrayBuffer对象的哪个字节开始,length属性表示视图中的元素个数。

在方法方面,TypedArray实现了数组接口,所以可以使用很多数组的方法,如map、filter、reduce等,同时它还有一些自己特有的方法,如copyWithin可以在数组内部复制元素 。

(三)DataView 视图:灵活的内存访问

DataView视图为我们提供了一种更灵活的方式来访问和操作ArrayBuffer中的数据。与TypedArray不同,DataView可以自定义数据的解析格式和字节序,这使得它在处理复杂二进制数据时非常有用。就像是一个万能的工具,可以根据我们的需求随意调整使用方式。

DataView的构造函数接受一个ArrayBuffer对象作为参数,还可以指定字节偏移量和视图长度。例如:

const buffer = new ArrayBuffer(16);
const dataView = new DataView(buffer, 4, 8);

这里创建了一个从buffer的第 4 个字节开始,长度为 8 个字节的DataView视图。

DataView提供了一系列方法来进行格式化的读写操作。比如getInt8、getUint8、getInt16、getUint16、getInt32、getUint32、getFloat32、getFloat64等方法用于读取不同类型的数据,setInt8、setUint8、setInt16、setUint16、setInt32、setUint32、setFloat32、setFloat64等方法用于写入数据。在读取和写入时,还可以指定字节序(大端序或小端序),以适应不同的系统和数据格式需求。

假设我们有一个包含特定格式二进制数据的ArrayBuffer,前 4 个字节是一个 32 位的无符号整数,接下来 4 个字节是一个 32 位的浮点数。使用DataView就可以这样读取

const buffer = new ArrayBuffer(8);
const dataView = new DataView(buffer);
dataView.setUint32(0, 1234567890);
dataView.setFloat32(4, 3.14159);

const uint32Value = dataView.getUint32(0);
const float32Value = dataView.getFloat32(4);
console.log(uint32Value); // 输出 1234567890
console.log(float32Value); // 输出 3.14159

在处理网络协议数据、文件格式解析等场景中,DataView的灵活性就能够充分发挥出来,帮助我们准确地处理各种复杂的二进制数据结构。

TS 中的二进制数组

(一)TS 类型系统中的二进制相关类型

在 TypeScript 中,数字类型可以表示二进制字面量。自 ECMAScript 2015 起,TypeScript 支持二进制字面量,通过在数字前加上0b或0B前缀来表示,如let binaryNumber: number = 0b1010;,这里的binaryNumber就是一个二进制表示的数字,其十进制值为 10。

在 TS 类型系统中,虽然没有专门的 “二进制数组” 类型,但我们可以使用number[]或Uint8Array等类型来表示包含二进制数据的数组。当使用number[]时,数组中的每个元素都是一个数字,这些数字可以用来表示二进制数据的各个位或字节 。例如,let binaryArray: number[] = [1, 0, 1, 1]; 这个数组可以看作是二进制数1011的一种表示形式。

Uint8Array在 TS 中也很常用,它是TypedArray的一种,专门用于处理 8 位无符号整数,非常适合表示二进制数据。通过类型注解,我们可以明确变量是Uint8Array类型,如let byteArray: Uint8Array = new Uint8Array([0x41, 0x42, 0x43]);,这里byteArray就是一个Uint8Array类型的数组,包含了三个字节的数据,分别对应字符'A'、'B'、'C'的 ASCII 码。

在类型推断方面,TS 会根据变量的赋值情况自动推断其类型。如果我们创建一个数组并赋值为二进制字面量,TS 会将其推断为number[]类型。比如let arr = [0b10, 0b11];,TS 会推断arr的类型为number[]。在使用TypedArray时,如果通过构造函数创建并传入合适的参数,TS 也能正确推断出其类型。

(二)TS 操作二进制数组的实践

在实际应用中,TypeScript 操作二进制数组的场景很多。以 LeetCode 1356 根据数字二进制下 1 的数目排序为例,题目要求我们对整数数组按照其二进制表示中数字 1 的数目升序排序,如果存在多个数字二进制中 1 的数目相同,则按数值大小升序排列。

function onesCount(x: number): number {
    let c = 0;
    while (x > 0) {
        c += x % 2;
        x = Math.floor(x / 2);
    }
    return c;
}

function sortByBits(arr: number[]): number[] {
    arr.sort((a, b) => {
        const cx = onesCount(a);
        const cy = onesCount(b);
        if (cx === cy) {
            return a - b;
        }
        return cx - cy;
    });
    return arr;
}

// 测试
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8];
console.log(sortByBits(arr)); 

在这段代码中,onesCount函数用于计算一个数字二进制表示中 1 的个数。通过不断对数字进行取模和除法运算,判断每一位是否为 1 并累加计数。sortByBits函数则利用Array.prototype.sort方法对数组进行排序,在排序比较函数中,先比较两个数字二进制中 1 的个数,如果相同再比较数字本身的大小 。

还有一种递推预处理的方法来解决这个问题:

function sortByBits(arr: number[]): number[] {
    // 计算每个数的二进制中1 的个数
    const bit: number[] = new Array(10001).fill(0);
    for (let i = 1; i <= 10000; ++i) {
        bit[i] = bit[i >> 1] + (i & 1);
    }
    // 深拷贝数组以避免原地修改
    const sortedArr = [...arr];
    // 使用自定义排序函数进行排序
    sortedArr.sort((x, y) => {
        if (bit[x] < bit[y]) {
            return -1;
        }
        if (bit[x] > bit[y]) {
            return 1;
        }
        return x - y;
    });
    return sortedArr;
}

这里先通过递推的方式预处理出每个数二进制中 1 的个数,存储在bit数组中。然后对原数组进行深拷贝,在排序时直接利用bit数组中的值进行比较,这样可以提高排序的效率 。在实际应用中,我们可以根据具体需求选择合适的方法来操作二进制数组,以实现高效的数据处理。

ArkTS 中的二进制数组

(一)ArkTS 的 TypedArray 与相关概念

在 ArkTS 中,TypedArray是处理二进制数据的关键工具。它是一种类数组数据视图,用于描述二进制数据,可看作是指定元素类型的数组 。TypedArray本身没有直接构造器,但可以通过它的子类构造器来创建相应类型的数据。

TypedArray的子类丰富多样,包括Int8Array(8 位有符号整数数组)、Uint8Array(8 位无符号整数数组)、Uint8ClampedArray(8 位无符号整数数组,溢出时会钳制值)、Int16Array(16 位有符号整数数组)、Int32Array(32 位有符号整数数组)等 。这些不同类型的数组视图,为开发者提供了灵活处理二进制数据的能力。

TypedArray具有一些显著特性。它是定长数组,长度在创建时就已确定,无法像普通数组那样动态调整长度,这在某些对内存和性能要求严格的场景中非常重要。TypedArray在处理二进制数据方面效率极高,特别适用于处理图像、音频等需要直接操作二进制数据的场景 。通过不同的视图类型,开发者可以根据数据的实际表示方式,选择最合适的数组类型来读取和操作内存数据,提高数据处理的准确性和效率。

例如,在处理图像数据时,图像的像素信息通常以二进制形式存储,使用Uint8Array可以直接读取和修改每个像素的颜色值,因为每个像素的颜色通道(如 RGB)通常可以用 8 位无符号整数来表示。在音频处理中,音频样本数据也可以用Int16Array等类型来存储和处理,以适应音频数据的特点 。

(二)ArkTS 二进制数组的应用场景

在鸿蒙开发中,ArkTS 二进制数组有着广泛的应用场景。在图像和视频处理领域,图像和视频数据本质上都是二进制数据。例如,在处理图像的像素数据时,我们可以使用Uint8Array来存储和操作每个像素的颜色值。假设我们要对一张图片进行灰度化处理,就可以通过Uint8Array读取每个像素的 RGB 值,然后根据灰度化算法将其转换为灰度值,再写回Uint8Array中,从而实现图像的灰度化。

在音频处理场景中,ArkTS 二进制数组同样发挥着重要作用。音频数据通常以采样的形式存储,每个采样点都代表了某一时刻的音频信号值。通过Int16Array等类型的二进制数组,我们可以方便地读取、修改和处理这些音频采样数据。比如,实现音频的降噪功能,就可以通过对二进制数组中的音频数据进行分析和处理,去除噪声部分,从而提高音频的质量 。

在网络通信方面,当我们进行数据传输时,数据往往以二进制的形式在网络中传输。ArkTS 中的二进制数组可以用于高效地处理这些网络数据。例如,在开发一个基于 WebSocket 的聊天应用时,接收到的消息数据可能是二进制格式的,我们可以使用Uint8Array等将其解析为文本或其他数据类型,然后进行相应的处理,再将处理后的回复数据转换为二进制数组发送出去 。在物联网设备开发中,与设备之间的通信数据也常常需要使用二进制数组来处理,以确保数据的准确传输和高效处理。

对比与总结

(一)JS、TS、ArkTS 二进制数组的异同

在语法层面,JavaScript 通过ArrayBuffer、TypedArray和DataView来操作二进制数组,语法较为灵活,开发者可以根据具体需求选择合适的方式。ArrayBuffer创建内存缓冲区,TypedArray提供不同数据类型的视图,DataView则实现更灵活的读写操作 。TypeScript 在 JS 的基础上,增加了类型注解,使得代码在操作二进制数组时类型更加明确。比如使用Uint8Array时,可以明确变量的类型为Uint8Array,避免类型错误 。ArkTS 的TypedArray同样用于处理二进制数据,虽然没有直接构造器,但通过子类构造器创建相应类型数据的方式,也具有独特的语法特点。

从功能角度来看,三者都提供了操作二进制数据的能力。JavaScript 的二进制数组功能全面,能满足各种常见的二进制数据处理需求,无论是简单的数据存储还是复杂的网络协议解析 。TypeScript 继承了 JavaScript 的二进制数组功能,并且借助其类型系统,增强了代码的健壮性和可维护性。在处理二进制数组时,可以在编译阶段发现类型相关的错误,减少运行时的错误发生 。ArkTS 的TypedArray在处理二进制数据时效率较高,尤其适用于处理图像、音频等需要大量二进制数据处理的场景。其定长数组的特性,在内存管理和性能优化方面具有一定优势 。

在应用场景方面,JavaScript 的二进制数组广泛应用于 Web 开发的各个领域。在 WebGL 中用于图形渲染,将顶点数据以二进制数组的形式传输给 GPU,实现高效的图形绘制;在音频处理中,能够快速处理音频样本数据,实现音频的播放、录制和编辑等功能 。TypeScript 由于其类型安全的特性,在大型项目和对代码质量要求较高的场景中更受欢迎。在开发复杂的前端应用时,使用 TypeScript 操作二进制数组可以提高代码的可读性和可维护性,方便团队协作开发 。ArkTS 的二进制数组主要应用于鸿蒙开发中,在图像、视频、音频处理以及网络通信等方面发挥重要作用。在鸿蒙系统的应用开发中,处理图像的像素数据、音频的采样数据以及网络传输的数据时,ArkTS 的二进制数组能够提供高效的解决方案 。

(二)实际应用中的选择与建议

如果是进行 Web 前端开发,且项目规模较小,对开发速度要求较高,JavaScript 的二进制数组是一个不错的选择。其灵活的语法和广泛的浏览器支持,可以快速实现二进制数据的处理功能。在一些简单的网页特效开发中,使用 JavaScript 操作二进制数组来处理图像数据,能够快速实现特效效果 。

当项目规模较大,需要更严格的类型检查和代码规范时,TypeScript 则更为合适。在企业级 Web 应用开发中,使用 TypeScript 操作二进制数组,可以在开发过程中及时发现类型错误,提高代码的稳定性和可维护性 。

对于鸿蒙应用开发,ArkTS 是首选语言,其TypedArray能够很好地适应鸿蒙系统的开发需求。在开发鸿蒙系统的图像编辑应用时,使用 ArkTS 的Uint8Array来处理图像的像素数据,能够充分利用其高效性和对鸿蒙系统的适配性 。

在实际应用中,还需要考虑团队的技术栈和项目的具体需求。如果团队对 JavaScript 或 TypeScript 比较熟悉,且项目是跨平台的 Web 应用,那么可以优先考虑 JavaScript 或 TypeScript;如果是专注于鸿蒙系统的应用开发,且团队有相关开发经验,那么 ArkTS 将是最佳选择 。同时,随着技术的不断发展,不同语言和框架之间的融合也越来越紧密,开发者可以根据实际情况灵活运用各种技术,以实现最佳的开发效果 。


http://www.kler.cn/a/549550.html

相关文章:

  • MySQL DELETE 语句
  • WPS的AI助手进化跟踪(灵犀+插件)
  • 人工智能 - 大脑神经网络与机器神经网络的区别
  • Deepseek R1模型本地化部署与API实战指南:释放企业级AI生产力
  • 数据库系统原理——第十一章并发控制复习题
  • 网络安全:从攻击到防御的全景解析
  • img标签的title和alt
  • Python实现微博关键词爬虫
  • Linux 基于共享内存的循环队列实现
  • 服务器中部署大模型DeepSeek-R1 | 本地部署DeepSeek-R1大模型 | deepseek-r1部署详细教程
  • Rocky Linux 9.4 安装 VirtualBox 7.1
  • 数据库索引使用 B+树和Java TreeMap 使用红黑树的原因
  • 硬件学习笔记--44 电磁兼容试验-8 振铃波试验介绍
  • 26. 未来一瞥:量子计算
  • HCIA项目实践--静态路由的综合实验
  • 【故障处理】- RMAN-06593: platform name ‘Linux x86 64-bitElapsed: 00:00:00.00‘
  • JDK1.8新特性面试题
  • 使用 Python 爬虫和 FFmpeg 爬取 B 站高清视频
  • 【limit 1000000,10 加载很慢该怎么优化?】
  • FPGA之​​​​​​​​​​​​​​HRBANK与HOBANK有什么区别?