鸿蒙Harmony角落里的知识:从ECMA规范到ArkTS接口(二)

2024-06-22 01:20

本文主要是介绍鸿蒙Harmony角落里的知识:从ECMA规范到ArkTS接口(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上篇介绍了typedArray.slice方法,鸿蒙Harmony角落里的知识:从ECMA规范到ArkTS接口(一)本文介绍一个返回结果和参数和slice非常类似的函数:TypedArray.prototype.subarray。


ECMA对TypedArray.prototype.subarray接口的定义:

按照ECMA的规范,TypedArray.prototype.subarray(begin, end) 方法定义如下:

  • begin: 起始索引,表示新视图的起始点。
  • end: 结束索引,代表新视图的终点(但不包括该索引本身)。

如果 end 参数省略,subarray 将默认包含从 begin 开始到原数组结尾的所有元素。如果 begin 或 end 是负值,则它们表示从数组末尾开始的倒数索引。方法返回一个新的 TypedArray 实例,它表示原始 TypedArray 的一个连续子集。

我们可以直接查看ECMA规范中对该函数的描述:

23.2.3.30 %TypedArray%.prototype.subarray ( start, end )This method returns a new TypedArray whose element type is the element type of this TypedArray and whose ArrayBuffer is the ArrayBuffer of this TypedArray, referencing the elements in the interval from start (inclusive) to end (exclusive). If either start or end is negative, it refers to an index from the end of the array, as opposed to from the beginning.It performs the following steps when called:1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
4. Let buffer be O.[[ViewedArrayBuffer]].
5. Let srcRecord be MakeTypedArrayWithBufferWitnessRecord(O, SEQ-CST).
6. If IsTypedArrayOutOfBounds(srcRecord) is true, thena. Let srcLength be 0.
7. Else,a. Let srcLength be TypedArrayLength(srcRecord).
8. Let relativeStart be ? ToIntegerOrInfinity(start).
9. If relativeStart = -∞, let startIndex be 0.
10. Else if relativeStart < 0, let startIndex be max(srcLength + relativeStart, 0).
11. Else, let startIndex be min(relativeStart, srcLength).
12. Let elementSize be TypedArrayElementSize(O).
13. Let srcByteOffset be O.[[ByteOffset]].
14. Let beginByteOffset be srcByteOffset + (startIndex × elementSize).
15. If O.[[ArrayLength]] is AUTO and end is undefined, thena. Let argumentsList be « buffer, 𝔽(beginByteOffset) ».
16. Else,a. If end is undefined, let relativeEnd be srcLength; else let relativeEnd be ? ToIntegerOrInfinity(end).b. If relativeEnd = -∞, let endIndex be 0.c. Else if relativeEnd < 0, let endIndex be max(srcLength + relativeEnd, 0).d. Else, let endIndex be min(relativeEnd, srcLength).e. Let newLength be max(endIndex - startIndex, 0).f. Let argumentsList be « buffer, 𝔽(beginByteOffset), 𝔽(newLength) ».
17. Return ? TypedArraySpeciesCreate(O, argumentsList).
This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

TypedArray.prototype.subarray与TypedArray.prototype.slice对比:

TypedArray.prototype.subarray 和 TypedArray.prototype.slice 是两个不同的 TypedArray 方法,用于生成原数组某部分的新数组,但他们在处理方式和结果的内存分配上存在差异。

首先,subarray 方法返回的新 TypedArray 对象,并不创建原 ArrayBuffer 的副本,而是创建了一个新的 TypedArray 视图,这个视图引用的是原 ArrayBuffer 中的相同内存区域。这意味着 subarray 方法生成的数组与原数组共享相同的数据存储,因此对新数组的修改会影响到原数组中相应的部分。这个方法的执行效率较高,因为它避免了复制操作,只是创建了一个指向相同内存区域的新视图。

另一方面,slice 方法会创建一个新的 ArrayBuffer,并将选定的元素从原 TypedArray 对象复制到新数组中。这意味着 slice 方法生成的新数组拥有自己的数据存储,对这个新数组的任何修改都不会影响原数组。由于涉及到内存中数据的复制操作,slice 方法在执行时的效率略低于 subarray

下面是这两个方法的对比分析:

  1. 内存共享与否
    • subarray:返回一个新 TypedArray,共享同一个 ArrayBuffer
    • slice:返回一个新 TypedArray,有自己独立的 ArrayBuffer
  2. 性能
    • subarray:性能较高,因为没有进行元素的复制,仅仅是创建了一个新的视图。
    • slice:性能较低,因为需要复制元素到新的 ArrayBuffer
  3. 修改影响
    • subarray:由于共享 ArrayBuffer,对生成的 TypedArray 的修改会影响到原数组。
    • slice:由于使用了新的 ArrayBuffer,对生成的 TypedArray 的修改不会影响到原数组。
  4. 参数处理
    • subarray 和 slice 方法对于 start 和 end 参数的处理是相同的。如果 start 或 end 是负数,它们会被解释为从数组末尾开始的索引。如果 end 是 undefined,则操作会处理直到原数组的末尾。
  5. 返回值类型
    • 无论是 subarray 还是 slice,返回的新数组类型都与原数组相同。
  6. 错误处理
    • slice 方法在复制过程中有更严格的错误检查。例如,如果源 TypedArray 越界,它会抛出 TypeError

总的来说,选择 subarray 还是 slice 取决于你是否需要一个独立的数组副本,以及是否关心性能和内存使用。如果你只是想要一个指向相同数据的快速视图,并且不介意对这个视图的修改会影响原数据,那么 subarray 是一个好选择。而如果你需要一个完全独立的复制,不会影响原数据的副本,那么应该选择 slice 方法。

ArkTS对subarray的接口描述:

我们继续以\static_core\plugins\ets\stdlib\escompat\TypedUArrays.ets的Uint8Array定义为例:

/*** Creates a Uint8Array with the same underlying Buffer** @param begin start index, inclusive** @param end last index, exclusive** @returns new Uint8Array with the same underlying Buffer*/public subarray(begin?: number, end?: number): Uint8Array {return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))}/*** Creates a Uint8Array with the same underlying Buffer** @param begin start index, inclusive** @param end last index, exclusive** @returns new Uint8Array with the same underlying Buffer*/public subarray(begin: number, end: number): Uint8Array {return this.subarray(begin as int, end as int)}/*** Creates a Uint8Array with the same underlying Buffer** @param begin start index, inclusive** @param end last index, exclusive** @returns new Uint8Array with the same underlying Buffer*/public subarray(begin: number, end: int): Uint8Array {return this.subarray(begin as int, end as int)}/*** Creates a Uint8Array with the same underlying Buffer** @param begin start index, inclusive** @param end last index, exclusive** @returns new Uint8Array with the same underlying Buffer*/public subarray(begin: int, end: number): Uint8Array {return this.subarray(begin as int, end as int)}/*** Creates a Uint8Array with the same underlying Buffer** @param begin start index, inclusive** @param end last index, exclusive** @returns new Uint8Array with the same underlying Buffer*/public subarray(begin: int, end: int): Uint8Array {const len: int = this.length as intconst relStart = normalizeIndex(begin, len)const relEnd = normalizeIndex(end, len)let count = relEnd - relStartif (count < 0) {count = 0}return new Uint8Array(this.buffer, relStart * Uint8Array.BYTES_PER_ELEMENT as int, count)}/*** Creates a Uint8Array with the same Buffer** @param begin start index, inclusive** @returns new Uint8Array with the same Buffer*/public subarray(begin: number): Uint8Array {return this.subarray(begin as int, this.lengthInt)}/*** Creates a Uint8Array with the same Buffer** @param begin start index, inclusive** @returns new Uint8Array with the same Buffer*/public subarray(begin: int): Uint8Array {return this.subarray(begin, this.lengthInt)}

ArkTS对subarray的接口定义如上,可以看到基本覆盖了ECMA的规范的方方面面。此外,我们还可以看到,subarray提供了对int类型参数的支持,而TS是仅仅只支持number类型的参数的。

测试用例:

要验证我们的 subarray 方法实现是否正确,我们可以编写单元测试用例。这里我们使用了ArkTS和Jest测试框架,来确保我们的实现与ECMA规范一致。

const success = 0;
const fail = 1;
function testSubarrayWithOutParam(): int {let source: number[] = [10, 20, 30, 40, 50, 60];let ss = new ArrayBuffer(source.length as int * 1);let origin: Uint8Array;try {origin = new Uint8Array(ss);origin.set(source);} catch(e) {console.log(e);return fail;}let target: Uint8Array;try {target = origin.subarray();} catch(e) {console.log(e);return fail;}if (target.length as int != origin.length as int) {console.log("Array length mismatch on slice");return fail;}//Check all the data copied;for (let i: int = 0; i< origin.length as int; i++) {let tv = target[i] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}origin= new Uint8Array(0);if (origin.length as int != 0){return fail;}try {target = origin.subarray();} catch(e) {console.log(e);return fail;}if (target.length as int != 0){return fail;}return success;
}function testSubarrayOneParam(): int {let source: number[] = [10, 20, 30, 40, 50, 60];let ss = new ArrayBuffer(source.length as int * 1);let origin: Uint8Array;try {origin = new Uint8Array(ss);origin.set(source);} catch(e) {console.log(e);return fail;}let subarrayStart: int = 1;let subarrayEnd: int = origin.length as int;let target: Uint8Array;try {target = origin.subarray(subarrayStart);} catch(e) {console.log(e);return fail;}if (target.length as int != origin.length as int - subarrayStart) {console.log("Array length mismatch on subarray One Params" + target.length);return fail;}//Check all the data copied;for (let i: int = subarrayStart; i< subarrayEnd; i++) {let tv = target[i - subarrayStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}subarrayStart = 0;try {target = origin.subarray(undefined);} catch(e) {console.log(e);return fail;}if (target.length as int != origin.length as int) {console.log("Array length mismatch on subarray One Params" + target.length);return fail;}//Check all the data copied;for (let i: int = subarrayStart; i< subarrayEnd; i++) {let tv = target[i - subarrayStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}//The subarray method returns a view of the original array, so modifications made to the subarray will affect the original array, and vice versa.target[subarrayStart] = 1;for (let i: int = subarrayStart; i< subarrayEnd; i++) {let tv = target[i - subarrayStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}origin[subarrayStart] = 2;for (let i: int = subarrayStart; i< subarrayEnd; i++) {let tv = target[i - subarrayStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}return success;
}function testSubarrayTwoParams(): int {let source: number[] = [10, 20, 30, 40, 50, 60, 70, 80];let ss = new ArrayBuffer(source.length as int * 1);let origin: Uint8Array;try {origin = new Uint8Array(ss);origin.set(source);} catch(e) {console.log(e);return fail;}let subarrayStart: int = 2;let subarrayEnd: int = 4;let target: Uint8Array;try {target = origin.subarray(subarrayStart, subarrayEnd);} catch(e) {console.log(e);return fail;}if (target.length as int != subarrayEnd - subarrayStart) {console.log("Array length mismatch on subarray2");return fail;}//Check all the data copied;for (let i: int = subarrayStart; i< subarrayEnd; i++) {let tv = target[i - subarrayStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}subarrayStart = 0;subarrayEnd = origin.length as int;try {target = origin.subarray(subarrayStart, subarrayEnd);} catch(e) {console.log(e);return fail;}if (target.length as int != subarrayEnd - subarrayStart) {console.log("Array length mismatch on subarray2");return fail;}//Check all the data copied;for (let i: int = subarrayStart; i< subarrayEnd; i++) {let tv = target[i - subarrayStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}try {target = origin.subarray(new Number(subarrayStart), undefined);} catch(e) {console.log(e);return fail;}if (target.length as int != subarrayEnd - subarrayStart) {console.log("Array length mismatch on subarray2");return fail;}//Check all the data copied;for (let i: int = subarrayStart; i< subarrayEnd; i++) {let tv = target[i - subarrayStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}try {target = origin.subarray(undefined, undefined);} catch(e) {console.log(e);return fail;}if (target.length as int != subarrayEnd - subarrayStart) {console.log("Array length mismatch on subarray2");return fail;}//Check all the data copied;for (let i: int = subarrayStart; i< subarrayEnd; i++) {let tv = target[i - subarrayStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}try {target = origin.subarray(undefined, new Number(subarrayEnd));} catch(e) {console.log(e);return fail;}if (target.length as int != subarrayEnd - subarrayStart) {console.log("Array length mismatch on subarray2");return fail;}//Check all the data copied;for (let i: int = subarrayStart; i< subarrayEnd; i++) {let tv = target[i - subarrayStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}try {target = origin.subarray(0, 0);} catch(e) {console.log(e);return fail;}if (target.length as int != 0) {console.log("Array length mismatch on subarray2");return fail;}return success;
}function testSubarrayTwoParamsWithOtherNumber(): int {let source: number[] = [10, 20, 30, 40, 50, 60, 70, 80];let ss = new ArrayBuffer(source.length as int * 1);let origin: Uint8Array;try {origin = new Uint8Array(ss);origin.set(source);} catch(e) {console.log(e);return fail;}let subarrayStart: int = 4;let subarrayEnd: int = 2;let target: Uint8Array;try {target = origin.subarray(subarrayStart, subarrayEnd);} catch(e) {return fail;}if (target.length as int != 0) {console.log("Array length mismatch on subarray2");return fail;}subarrayStart = -1;subarrayEnd = origin.length as int;try {target = origin.subarray(subarrayStart, subarrayEnd);} catch(e) {return fail;}if (target.length as int != subarrayEnd - (origin.length + subarrayStart)) {console.log("Array length mismatch on subarray2");return fail;}//Check all the data copied;for (let i: int = (origin.length + subarrayStart) as int; i< subarrayEnd; i++) {let tv = target[i - (origin.length + subarrayStart)] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if (tv != ov) {console.log("Array data mismatch");return fail;}}subarrayStart = 0;subarrayEnd = -origin.length as int;try {target = origin.subarray(subarrayStart, subarrayEnd);} catch(e) {console.log(e);return fail;}if (target.length as int != (origin.length + subarrayEnd) - subarrayStart) {console.log("Array length mismatch on subarray2");return fail;}return success;
}function testSubarrayOneLengthTwoParams(): int {let source: number[] = [10];let ss = new ArrayBuffer(source.length as int * 1);let origin: Uint8Array;try {origin = new Uint8Array(ss);origin.set(source);} catch(e) {console.log(e);return fail;}let subarrayStart: int = 4;let subarrayEnd: int = 2;let target: Uint8Array;try {target = origin.subarray(subarrayStart, subarrayEnd);} catch(e) {return fail;}if (target.length as int != 0) {console.log("Array length mismatch on subarray2");return fail;}subarrayStart = 2;subarrayEnd = 4;try {target = origin.subarray(subarrayStart, subarrayEnd);} catch(e) {return fail;}if (target.length as int != 0) {console.log("Array length mismatch on subarray2");return fail;}return success;
}

这些测试用例检查了 subarray 方法在正常条件下和非正常条件下的行为,对比slice函数的测试用例,我们使用通过修改源数组影响目标数组数值的方式验证内存共享的功能。

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?但是又不知道从哪里下手,而且学习时频繁踩坑,最终浪费大量时间。所以本人整理了一些比较合适的鸿蒙(HarmonyOS NEXT)学习路径和一些资料的整理供小伙伴学习

点击领取→纯血鸿蒙Next全套最新学习资料(安全链接,放心点击

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

一、鸿蒙(HarmonyOS NEXT)最新学习路线

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)…等技术知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

二、HarmonyOS Next 最新全套视频教程

三、《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

四、大厂面试必问面试题

五、鸿蒙南向开发技术

六、鸿蒙APP开发必备

七、鸿蒙生态应用开发白皮书V2.0PDF


完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

                        

这篇关于鸿蒙Harmony角落里的知识:从ECMA规范到ArkTS接口(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1082886

相关文章

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

sqlite3 相关知识

WAL 模式 VS 回滚模式 特性WAL 模式回滚模式(Rollback Journal)定义使用写前日志来记录变更。使用回滚日志来记录事务的所有修改。特点更高的并发性和性能;支持多读者和单写者。支持安全的事务回滚,但并发性较低。性能写入性能更好,尤其是读多写少的场景。写操作会造成较大的性能开销,尤其是在事务开始时。写入流程数据首先写入 WAL 文件,然后才从 WAL 刷新到主数据库。数据在开始

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

JavaEE7 Servlet 3.1(JSR 340)规范中文版

http://www.iteye.com/news/27727-jinnianshilongnian     Jave EE 7中的部分规范已正式获得批准通过,其中包括JSR340 Java Servlet 3.1规范,去年翻译了该规范,在此分享出来,希望对某些朋友有所帮助,不足之处请指正。   点击直接下载    在线版目录   Servlet3.1规范翻译

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu

模拟实现vector中的常见接口

insert void insert(iterator pos, const T& x){if (_finish == _endofstorage){int n = pos - _start;size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);pos = _start + n;//防止迭代

京东物流查询|开发者调用API接口实现

快递聚合查询的优势 1、高效整合多种快递信息。2、实时动态更新。3、自动化管理流程。 聚合国内外1500家快递公司的物流信息查询服务,使用API接口查询京东物流的便捷步骤,首先选择专业的数据平台的快递API接口:物流快递查询API接口-单号查询API - 探数数据 以下示例是参考的示例代码: import requestsurl = "http://api.tanshuapi.com/a