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

2024-06-21 17:44

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

 前言:

在深入理解和使用ArkTS中的数组操作之前,我们有必要先了解ECMAScript(ECMA)规范中的规定。ECMA规范是JavaScript语言的官方标准,而ArkTS作为JavaScript的超集,也遵守了这些规定。本系列文章旨在探讨ECMA规范如何定义接口,以及如何在ArkTS该接口如何使用。

ECMA对typedArray.slice接口的定义

在ECMA规范中,typedArray 是一个泛型对象,表示一个固定长度的二进制数据缓冲区,并且可以用来创建多种类型的视图,比如 Uint8ArrayInt16ArrayFloat32Array 等。而其中的 .slice() 方法,用于浅复制 typedArray 的一部分到一个新的 typedArray 实例。

根据ECMAScript规范,typedArray.slice(begin, end) 方法接受两个参数:begin 表示起始位置,end 表示结束位置(不包含)。如果不提供 end 参数,slice 方法会复制从 begin 到原数组末尾的所有元素。如果 begin 或 end 是负数,则表示从数组末尾开始的偏移量。返回值是一个新的 typedArray 实例,包含指定范围的元素。

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

23.2.3.27 %TypedArray%.prototype.slice ( start, end )
The interpretation and use of the arguments of this method are the same as for Array.prototype.slice as defined in 23.1.3.28.This method performs the following steps when called:
1. Let O be the this value.
2. Perform ? ValidateTypedArray(O).
3. Let len be O.[[ArrayLength]].
4. Let relativeStart be ? ToIntegerOrInfinity(start).
5. If relativeStart = -∞, let k be 0.
6. Else if relativeStart < 0, let k be max(len + relativeStart, 0).
7. Else, let k be min(relativeStart, len).
8. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
9. If relativeEnd = -∞, let final be 0.
10. Else if relativeEnd < 0, let final be max(len + relativeEnd, 0).
11. Else, let final be min(relativeEnd, len).
12. Let count be max(final - k, 0).
13. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(count) »).
14. If count > 0, thena. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.b. Let srcType be TypedArrayElementType(O).c. Let targetType be TypedArrayElementType(A).d. If srcType is targetType, theni. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.ii. Let srcBuffer be O.[[ViewedArrayBuffer]].iii. Let targetBuffer be A.[[ViewedArrayBuffer]].iv. Let elementSize be TypedArrayElementSize(O).v. Let srcByteOffset be O.[[ByteOffset]].vi. Let srcByteIndex be (k × elementSize) + srcByteOffset.vii. Let targetByteIndex be A.[[ByteOffset]].viii. Let limit be targetByteIndex + count × elementSize.ix. Repeat, while targetByteIndex < limit,1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, Uint8, true, Unordered).2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, Uint8, value, true, Unordered).3. Set srcByteIndex to srcByteIndex + 1.4. Set targetByteIndex to targetByteIndex + 1.e. Else,i. Let n be 0.ii. Repeat, while k < final,1.Let Pk be ! ToString(𝔽(k)).2.Let kValue be ! Get(O, Pk).3.Perform ! Set(A, ! ToString(𝔽(n)), kValue, true).4.Set k to k + 1.5.Set n to n + 1.
15. Return A.
This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

大家可以看到,ECMA规范中对接口的描述非常详细,对各种参数的输入和输出都做非常细致的说明,无论是符合标准的语言接口的实现,还是

ArkTS对slice的接口描述

在ArkTS中,接口(Interfaces)是一个非常强大的特性,允许开发者定义对象的类型。为了实现一个符合ECMA规范的 slice 方法,ArkTS对该方法的定义声明如下:

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

/*** Creates a slice of current Uint8Array using range [begin, end)** @param begin start index to be taken into slice** @param end last index to be taken into slice** @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded** @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice*/public slice(begin?: Number, end?: Number): Uint8Array {return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))}/*** Creates a slice of current Uint8Array using range [begin, end)** @param begin start index to be taken into slice** @param end last index to be taken into slice** @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded** @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice*/public slice(begin: number, end: number): Uint8Array {return this.slice(begin as int, end as int)}/*** Creates a slice of current Uint8Array using range [begin, end)** @param begin start index to be taken into slice** @param end last index to be taken into slice** @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded** @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice*/public slice(begin: number, end: int): Uint8Array {return this.slice(begin as int, end as int)}/*** Creates a slice of current Uint8Array using range [begin, end)** @param begin start index to be taken into slice** @param end last index to be taken into slice** @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded** @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice*/public slice(begin: int, end: number): Uint8Array {return this.slice(begin as int, end as int)}/*** Creates a slice of current Uint8Array using range [begin, end)** @param begin start index to be taken into slice** @param end last index to be taken into slice** @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded** @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice*/public slice(begin: int, end: int): Uint8Array {const len: int = this.lengthIntconst relStart = normalizeIndex(begin, len)const relEnd = normalizeIndex(end, len)let count = relEnd - relStartif (count < 0) {count = 0}if (this.buffer instanceof ArrayBuffer) {let buf = (this.buffer as ArrayBuffer).slice(relStart * Uint8Array.BYTES_PER_ELEMENT as int, relEnd * Uint8Array.BYTES_PER_ELEMENT as int) as ArrayBufferreturn new Uint8Array(buf)} else if (this.buffer instanceof SharedArrayBuffer) {let buf = (this.buffer as SharedArrayBuffer).slice(relStart * Uint8Array.BYTES_PER_ELEMENT as int, relEnd * Uint8Array.BYTES_PER_ELEMENT as int) as SharedArrayBufferreturn new Uint8Array(buf)} else {throw new Error("unexpected type of buffer")}}/*** Creates a slice of current Uint8Array using range [begin, this.lengthInt).** @param begin start index to be taken into slice** @returns a new Uint8Array with elements of current Uint8Array[begin, this.lengthInt)*/public slice(begin: number): Uint8Array {return this.slice(begin as int)}/*** Creates a slice of current Uint8Array using range [begin, this.lengthInt).** @param begin start index to be taken into slice** @returns a new Uint8Array with elements of current Uint8Array[begin, this.lengthInt)*/public slice(begin: int): Uint8Array {return this.slice(begin, this.lengthInt)}

在这个例子中,我们创建了一个 Int32ArrayWithSlice 类,它实现了 TypedArray 接口,包含了符合ECMA规范的 slice 方法。这个方法返回的是 Int32ArrayWithSlice 的新实例,包含了切片后的元素。

测试用例

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

const success = 0;
const fail = 1;
function testSliceWithOutParam(): 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.slice();} 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.slice();} catch(e) {console.log(e);return fail;}if(target.length as int != 0){return fail;}return success;
}function testSliceOneParam(): 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 sliceStart: int = 1;let sliceEnd: int = origin.length as int;let target: Uint8Array;try {target = origin.slice(sliceStart);} catch(e) {console.log(e);return fail;}if(target.length as int != origin.length as int - sliceStart) {console.log("Array length mismatch on slice One Params" + target.length);return fail;}//Check all the data copied;for(let i:int = sliceStart; i< sliceEnd; i++) {let tv = target[i - sliceStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if(tv != ov) {console.log("Array data mismatch");return fail;}}sliceStart = 0;try {target = origin.slice(undefined);} catch(e) {console.log(e);return fail;}if(target.length as int != origin.length as int) {console.log("Array length mismatch on slice One Params" + target.length);return fail;}//Check all the data copied;for(let i:int = sliceStart; i< sliceEnd; i++) {let tv = target[i - sliceStart] 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 testSliceTwoParams(): 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 sliceStart: int = 2;let sliceEnd: int = 4;let target: Uint8Array;try {target = origin.slice(sliceStart, sliceEnd);} catch(e) {console.log(e);return fail;}if(target.length as int != sliceEnd - sliceStart) {console.log("Array length mismatch on slice2");return fail;}//Check all the data copied;for(let i:int = sliceStart; i< sliceEnd; i++) {let tv = target[i - sliceStart] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if(tv != ov) {console.log("Array data mismatch");return fail;}}sliceStart = 0;sliceEnd = origin.length as int;try {target = origin.slice(sliceStart, sliceEnd);} catch(e) {console.log(e);return fail;}if(target.length as int != sliceEnd - sliceStart) {console.log("Array length mismatch on slice2");return fail;}//Check all the data copied;for(let i:int = sliceStart; i< sliceEnd; i++) {let tv = target[i - sliceStart] 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.slice(new Number(sliceStart), undefined);} catch(e) {console.log(e);return fail;}if(target.length as int != sliceEnd - sliceStart) {console.log("Array length mismatch on slice2");return fail;}//Check all the data copied;for(let i:int = sliceStart; i< sliceEnd; i++) {let tv = target[i - sliceStart] 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.slice(undefined, undefined);} catch(e) {console.log(e);return fail;}if(target.length as int != sliceEnd - sliceStart) {console.log("Array length mismatch on slice2");return fail;}//Check all the data copied;for(let i:int = sliceStart; i< sliceEnd; i++) {let tv = target[i - sliceStart] 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.slice(undefined, new Number(sliceEnd));} catch(e) {console.log(e);return fail;}if(target.length as int != sliceEnd - sliceStart) {console.log("Array length mismatch on slice2");return fail;}//Check all the data copied;for(let i:int = sliceStart; i< sliceEnd; i++) {let tv = target[i - sliceStart] 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.slice(0, 0);} catch(e) {console.log(e);return fail;}if(target.length as int != 0) {console.log("Array length mismatch on slice2");return fail;}return success;
}function testSliceTwoParamsWithOtherNumber(): 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 sliceStart: int = 4;let sliceEnd: int = 2;let target: Uint8Array;try {target = origin.slice(sliceStart, sliceEnd);} catch(e) {return fail;}if(target.length as int != 0) {console.log("Array length mismatch on slice2");return fail;}sliceStart = -1;sliceEnd = origin.length as int;try {target = origin.slice(sliceStart, sliceEnd);} catch(e) {return fail;}if(target.length as int != sliceEnd - (origin.length + sliceStart)) {console.log("Array length mismatch on slice2");return fail;}//Check all the data copied;for(let i:int = (origin.length + sliceStart) as int; i< sliceEnd; i++) {let tv = target[i - (origin.length + sliceStart)] as number;let ov = origin[i] as number;console.log(source[i] + "->" + tv + "->" + ov);if(tv != ov) {console.log("Array data mismatch");return fail;}}sliceStart = 0;sliceEnd = -origin.length as int;try {target = origin.slice(sliceStart, sliceEnd);} catch(e) {console.log(e);return fail;}if(target.length as int != (origin.length + sliceEnd) - sliceStart) {console.log("Array length mismatch on slice2");return fail;}return success;
}function testSliceOneLengthTwoParams(): 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 sliceStart: int = 4;let sliceEnd: int = 2;let target: Uint8Array;try {target = origin.slice(sliceStart, sliceEnd);} catch(e) {return fail;}if(target.length as int != 0) {console.log("Array length mismatch on slice2");return fail;}sliceStart = 2;sliceEnd = 4;try {target = origin.slice(sliceStart, sliceEnd);} catch(e) {return fail;}if(target.length as int != 0) {console.log("Array length mismatch on slice2");return fail;}return success;
}

这些测试用例检查了 slice 方法在正常条件下和非正常条件下的行为。通过运行这些测试,我们可以确认我们的实现是否符合接口定义预期和ECMA规范。

总结来说,理解ECMA规范中的接口是任何ArkTS开发者的基本功,而且通过单元测试可以保证实现的准确性和可靠性。通过逐步实现这些接口并验证它们的行为,我们可以确保我们的ArkTS代码既强大又稳健。


最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?但是又不知道从哪里下手,而且学习时频繁踩坑,最终浪费大量时间。所以本人整理了一些比较合适的鸿蒙(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/1081902

相关文章

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

vue3项目将所有访问后端springboot的接口统一管理带跨域

vue3项目将所有访问后端springboot的接口统一管理带跨域 一、前言1.安装Axios2.创建Axios实例3.创建API服务文件4.在组件中使用API服务 二、跨域三、总结 一、前言 在Vue 3项目中,统一管理所有访问后端Spring Boot接口的最佳实践是创建一个专门的API服务层。这可以让你的代码更加模块化、可维护和集中管理。你可以使用Axios库作为HTT

【鸿蒙】ERROR_GET_BUNDLE_INSTALLER_FAILED

错误信息 [ERROR_GET_BUNDLE_INSTALLER_FAILED] Troubleshooting guide $ hdc file send D:\Huawei\devEcoProjects\entry\build\default\outputs\default\entry-default-unsigned.hap /sdcard/e8a215ea7be1444197e6a58e

linux常用API接口

linux常用API接口 文章目录 linux常用API接口1.应用层内存映射mmap取消内存映射munmap终端打印可用方式1.puts 函数2.文件操作函数 fprintf3.字符输出函数 putchar4.fwrite 函数 2.内核层 1.应用层 内存映射mmap mmap 是一个用于内存映射的系统调用,它可以将一个文件或设备中的内容映射到进程的地址空间中,允许程

ArkTS开发系列之导航 (2.7动画)

上篇回顾: ArkTS开发系列之导航 (2.6 图形) 本篇内容:动画的学习使用 一、 知识储备 1. 布局更新动画 包含显式动画(animateTo)和属性动画(animation) 动画类型名称特点显式动画闭包内的变化都会触发动画执行, 可以做较复杂的动画属性动画属性变化时触发动画执行, 设置简单 说白了,显示动画就是靠闭包事件触发,属性动画是挂在组件身上的属性变化触发 显式动画

关于CPU的一点知识

首先说一下,CPU是干啥的: CPU所负责的就是解释和运行最终转换成机器语言的程序内容 我们需要知道的CPU结构:重点需要关注寄存器 运算器 简单说就是负责运算从内存读取到寄存器中的数据,可以看作一个数据加工厂,就是对寄存器中的数据做运算,这些运算包含基本的算术和逻辑运算。 算术逻辑单元(ALU) 这个是运算器中重要的一个组成,主要负责的就是对数据的处理,从而实现对数据的算术和

关于微信没有接入鸿蒙NEXT的思考

6月21日,纯血鸿蒙发布,国内的质疑声终于停止,不再被人喊叫换皮 Android 了.就连编程语言都是华为自研的。 可是发布会后微信却成了热点,因为余承东在感谢了一圈互联网企业,如:淘宝、支付宝、美团、京东、抖音、今日头条、钉钉、小红书、微博、B站、高德、WPS等等. 唯独没有感谢腾讯. 中国互联网巨头只有哪么几家,腾讯、阿里、字节、拼多多、美团、百度、京东、华为 他们这些派系又诞生了无数

上位机图像处理和嵌入式模块部署(mcu和swd接口)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         最近学习mcu的时候,接触了不少调试器,这里面有daplink、st-link v2、j-link v9。虽然模块的形状可能不太一样,但是硬件的连线都差不多,都是mcu上的3.3v、clk、dio和gnd四根连线。出于好奇,今天花了点时间了解了一下debug port、sw

【架构设计】模块化-面向接口编程

模块化的优势 结构清晰:业务独立,代码实现分离便于协作:耦合度低,不会影响团队其他成员的开发进度便于维护:各模块管理自身代码、布局、资源,不影响主工程 模块化的特点 高内聚,低耦合 常见的模块化方法 所有模块都放在一个工程里实现每个模块都放在一个独立工程中实现 模块的划分 从高到低 业务层平台能力层基础层 模块间的通信 直接依赖事件或广播通信路由通信面向接口通信 具体实现

使用ig507金融数据库的股票API接口经验有感:Java与Python

一、Java技术: 1. Java调用ig507金融数据库(ig507.com)股票API接口 引言: 随着金融科技的不断发展,数据驱动的投资策略变得越来越重要。本文将介绍如何使用Java语言调用ig507金融数据库的股票API接口,以获取实时股票数据,并展示基本的编程步骤和注意事项。 步骤一:引入依赖库 在Java项目中,首先需要引入用于处理HTTP请求和网络通信的库,如Apache