ArkTS collections.Array 机制解析:为什么需要区别于 JavaScript Array
大家好,我是新手程序员Kevin(小K),今天是我自学ArkTS 的第一天。之前有一点TS的开发经验,但不多
这次学习的是从 ArkTS 中 collections.Array 这个类开始。刚看到文档的时候,我其实有点疑惑,因为平时写 TypeScript 或 JavaScript 时已经习惯使用原生 Array,所以一开始并不太理解为什么 ArkTS 还要单独提供一个 collections.Array,两者之间是否有什么差异需要注意?往后看文档后慢慢意识到,这个类其实是为了并发场景以及 Sendable 数据传递设计的,这一点算是我这次学习中最关键的理解点之一。
首先从整体概念上看,collections.Array 本质上还是一种线性数据结构,底层仍然基于数组实现。和普通数组一样,它也有索引、长度、遍历等基本能力。不过 ArkTS 的这个实现有一个很重要的特点:可以在并发实例之间传递。文档里提到,当需要在并发实例之间传递 Array 时,可以直接传递 Array 的引用,这样能提高性能。我理解这里其实是在减少数据拷贝,类似共享对象引用的思路。
在使用上,需要先导入模块:
import { collections } from '@kit.ArkTS';
然后通过 new collections.Array<T>() 来创建数组对象。这里的泛型 T 必须是 Sendable 类型。这一点我一开始有点没太注意,直到看到 Array.from 的示例才意识到这个限制的重要性。比如普通的 Array<Array<string>> 在这里就会报错,因为 Array<string> 本身不是Sendable 类型。这一点在并发系统里其实挺合理的,毕竟可传递对象必须保证安全。
创建数组主要有几种方式:
第一种是最普通的构造函数:
let array = new collections.Array<number>();
第二种是初始化元素:
let array = new collections.Array<number>(1,2,3,4);
第三种是利用展开运算符初始化:
let arrayPara = [1,2,3];
let array = new collections.Array<number>(...arrayPara);
这里我注意到 ArkTS 的 Array 在初始化时其实和 JS 的写法很接近,所以理解起来没有太大难度。
另外还有几个静态方法我觉得比较实用,比如 create、from、of。
create 可以创建固定长度数组:
collections.Array.create<number>(3,10)
结果是 [10,10,10]。这个在需要初始化数据结构时应该挺方便,比如初始化缓存或者状态数组。
from 的功能比较多,可以从 ArrayLike 或 Iterable 对象生成新数组。我第一次看到这里的时候其实没太理解 ArrayLike 的意义,后来查了一下发现像 arguments 或某些类数组对象都属于这个范畴。还有一个挺有意思的是 API 18 之后增加了带 mapFn 的版本,可以在创建数组时直接对元素进行转换,这点和 JS 的 Array.from() 很像。
collections.Array.from(array, (value,index)=>value+index)
还有一个 isArray() 方法也挺直接,用来判断对象是不是 ArkTS Array。
接下来是各种实例方法。整体看下来,我感觉可以大致分成几类。
第一类是增删操作
比如:
push()在末尾添加元素pop()删除最后一个shift()删除第一个unshift()在头部插入
这些操作逻辑基本和 JS 数组一样,比如:
array.push(4,5)
array.pop()
第二类是查找与判断
例如:
indexOflastIndexOfincludesfindfindIndexsomeevery
这些 ArkTS 里的方法,用法上大多也和JS或TS基本保持一致,感觉 API 设计上是完全继承,没什么特别需要注意的。
第三类是遍历与转换
包括:
forEachmapfilterreducereduceRight
其中map和filter是我平时用得最多的。
例如:
array.map(value => value.toUpperCase())
会返回一个新的数组。
reduce 和 reduceRight 则是用来做累加计算或者聚合操作,比如求和:
array.reduce((acc,value)=>acc+value)
一开始看到 reduceRight 我其实有点没太理解,因为平时很少用。虽然用得少,但在某些数据处理逻辑里可能会有用。
第四类是数组结构操作
例如:
slice()截取数组splice()删除或插入元素concat()拼接数组copyWithin()内部复制元素reverse()反转数组sort()排序
这里splice我感觉是最复杂的,因为参数比较多。它既能删除元素,又能插入元素。例如示例中的:
array.splice(2,2,6,7,8)
意思是从 index=2 开始删除两个元素,然后插入新的值。虽然和JS里的用法一致,但之前从来没这么用过,今天读技术文档,也算温故而知新的一个知识点。
第五类是数组内容处理
例如:
fill()用指定值填充join()拼接字符串toString()toLocaleString()
toLocaleString()这个我之前很少注意。文档举例说,如果系统地区是法国,数字格式会自动带千位分隔符。这个感觉平时用不到,可能做国际化时会有用。
还有两个比较特别的方法:
shrinkTo()和extendTo()
这两个是普通 JS 数组没有的功能。shrinkTo(n)会把数组缩短到指定长度extendTo(n,value)会扩展数组并用指定值填充
比如:
array.extendTo(5,10)
会把数组扩展到长度 5,并用 10 填充新位置。
我个人感觉这个设计很像某些系统语言里的容器操作,可能也是为了更好地控制内存结构。
另外还有一些迭代器相关的方法:
entries()keys()values()
这些会返回可迭代对象,用for...of可以遍历。
最后一个比较细节的是at(index)。这个方法支持负索引,比如at(-1)就能获取最后一个元素。这个设计我觉得挺好,之前做的TS项目中,没找到这样的负索引表示方式,感觉引用了python的语法逻辑,比array[array.length-1]更直观。
整个文档看下来,我最大的感受其实是:ArkTS 的 Array API 基本延续了 JavaScript 的设计,但又加入了一些并发安全和系统级能力。
一开始我其实有点低估这个类,以为只是普通数组的简单封装。但仔细看完后发现它其实解决的是Sendable数据结构的问题,这在 ArkTS 的并发模型里是非常关键的。
有几个地方让我卡了一下。比如 Sendable 类型限制,还有 ArrayLike 的概念。如果只是粗略看代码示例,很容易忽略这些限制。但一旦涉及跨实例传递数据,这些约束就会变得非常重要。
开始阅读ArkTS文档之前我更多关注 UI 或组件开发,但现在慢慢意识到底层数据结构同样很重要。特别是在鸿蒙这种强调分布式和并发的系统里,数据结构的设计其实直接影响性能和安全。
后面我打算开始写几个自己的小练习、小Demo,我会把后面实战的内容也分享到51CTO,既是交流,也是对自己学习过程的记录。
相信实际这样用几次,应该能把这些 API 用得更熟一点。
在51CTO的第一篇文章,很多地方还在摸索中,排版和表达如果有不规范的地方,还请大家多多见谅,多提意见。
更多推荐



所有评论(0)