【HarmonyOS NEXT】ArkTs数据类型解析与使用

1. 背景

  1. 为什么设计ArkTS?
    1.1 其它语言有版权【Java?Kotlin?】以及历史问题【Java内存?】
    1.2 生态,可复用前端生态的三方库,兼容JS/TS语言生态
  2. ArkTs解决了JS/TS中的哪些问题?
    2.1 **程序健壮性:**JS是动态类型【运行期间才去做数据类型检查,且类型可以随便改变】,不利于程序的健壮性。
    2.2 **性能问题:**TS虽然是静态类型,但是它的类型检查可配置可关闭,而且编译后类型信息丢失,会增加运行的时编译和执行字节码耗时。ArkCompiler利用ArkTS的静态类型信息,进行类型推导并生成对象描述和内联缓存,**加速运行时对字节码的解释执行;**AOT(Ahead-of-Time)Compiler利用静态类型信息直接将字节码编译生成优化机器码,让应用启动即可运行高性能代码,提升应用启动和运行性能。
    2.3 JS运行流程: 解析源码>编译字节码>执行字节码>获取Profile信息>编译优化机器码>执行优化机器码
    2.4 ArkTS编译流程: 解析源码>编译字节码>获取Profile信息>编译优化机器码>打包字节码和优化字节码
    2.5 ArkTS运行流程: 执行优化机器码>执行字节码
    2.6 安全: ArkCompiler会把ArkTS/TS/JS编译为方舟字节码,运行时直接运行方舟字节码。并且ArkCompiler使用多种混淆技术提供更高强度的混淆与保护,使得HarmonyOS应用包中装载的是多重混淆后的字节码,有效提高了应用代码安全的强度。
    2.7 并发: JS/TS 中并发的API不够简洁,而且支撑不了复杂业务的开发场景,而ArkTS中的TaskPool会绑定系统的调度优先级,并且支持负载均衡(自动扩缩容),可支撑各种业务场景

2. 前言

  无论是Android还是iOS开发,都提供了多种数据类型用于常见的业务开发,和Java/Objective-C一样ArkTs也有很多和Java/Objective-C中相同的数据类型,当然也有不同的。
  ArkTS和JS\TS之间的关系

关于ES 是什么,可以看我这边整理的一篇文章 Javascript[ECMAScript] ES6、ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14[2023]新特性

  ArkTS是TypeScript的超集,其数据类型也是基于TypeScript而来,除了原始5种数据类型之外,还有一些 ECMAScript 中的新类型,以及包含常见的枚举、任意类型等等,大概有十多种,但常用的就那么几种。

数据类型汇总如下:

数据类型包装类概述
numberNumber数字类型
booleanBoolean布尔类型
stringString字符串类型
objectObject对象
ArrayArray
tuple元组类型
enum枚举类型
union联合类型
undefined一个未定义或不存在的值
null
aliases匿名类型
BigInt任意大的数
void没有任何返回值的类型

为了保证开发正确性和性能,ArkTS中取消了JS中的symbol类型,以及TS中的unknown 和any类型

3. 类型声明

3.1 变量声明

  以关键字let开头的声明引入变量,该变量在程序执行期间可以具有不同的值。【注意,这里不能使用JS/TS中的var,因为let关键字可以在块级作用域中声明变量,帮助程序员避免错误。因此,ArkTS不支持var,请使用let声明变量。】

这里的let 类似于kotlin中的var

let hi: string = 'hello';
hi = 'hello, world';

3.2 常量声明

  以关键字const开头的声明引入只读常量,该常量只能被赋值一次。对常量重新赋值会造成编译时错误。

这里的const 类似于kotlin中的val

const hello: string = 'hello';

3.3 自动类型推断

  由于ArkTS是一种静态类型语言,所有数据的类型都必须在编译时确定。
但是,如果一个变量或常量的声明包含了初始值,那么开发者就不需要显式指定其类型。ArkTS规范中列举了所有允许自动推断类型的场景。

以下示例中,两条声明语句都是有效的,两个变量都是string类型

let hi1: string = 'hello';
let hi2 = 'hello, world';
//使用JS的同学注意了:这里和JS不一样,ArkTS中一旦类型初始化的时候就确定了,之后就无法更改。例如:
// hi2 = 123// 错误
flag = '你好世界'  //正确

4. 基础数据类型

JavaScript中存在两套类型系统分别为原生类型(Base types)和对象类型(Object types)【类似于Java中装箱和拆箱】,ArkTS也继承了这一特性。
对象类型和原生类型相比,会提供一些额外的方法,例如string和String

let msg: string = 'Hello world!';
let msg2: String = 'Hello world!';
let msg22 = 'Hello world!';  //字面上没有定义类型
let msg3: String = new String('Hello world!');console.log(typeof(msg));  //string
console.log(typeof(msg2));  //string
console.log(typeof(msg22));  //string
console.log(typeof(msg3));  //object
console.log((msg === msg2)+"");  //true
console.log((msg === msg3)+"");  //false
console.log((msg2 === msg3)+"");  //false

4.1 Number类型

  凡是表示数值的,不管是二进制还是八进制,还是其他进制,长整数,小数,负数等等,只有一个类型表示,那就是number。
局部声明须带关键字

4.1.1 原生number

let a: number = 0 //整数
let b: number = -100 //负数
let c: number = 88.88 //小数
let d: number = 0b1010 //二进制 ES6
let e: number = 0o744 //八进制  ES6

4.1.2 对象Number

let a: Number = new Number(0) //整数
let b: Number = new Number(-100) //负数
let c: Number = new Number(88.88) //小数
let d: Number = new Number(0b1010) //二进制 ES6
let e: Number = new Number(0o744) //八进制  ES6

4.1.3 上限

  在ArkTS中,Number类型的上限由JavaScript的Number类型的上限决定,因为ArkTS的Number类型是基于JavaScript的Number类型。
  JavaScript中的Number类型是基于IEEE 754标准的双精度浮点数表示,它的上限由标准规定为1.7976931348623157e+308。这意味着JavaScript中的Number类型可以表示的最大值是约1.8 x 10^308。

const maxNumber: number = Number.MAX_VALUE;
console.log(maxNumber.toString()); // 输出 1.7976931348623157e+308const infinity: number = Number.MAX_VALUE * 2;
console.log(infinity.toString()); // 输出 Infinity

【必看】注意注意:

  因为ArkTS的Number类型是基于JavaScript的Number类型。那么在JS中著名精度丢失问题,在ArkTS中也依旧存在,这里想起一张图。。。此处先只解决图里面精度丢失的问题,其它问题后续会出详细的文档来说明和解决。

**解决办法:**可以用成熟的三方库来解决:https://ohpm.openharmony.cn/#/cn/detail/bignumber.js

【鸿蒙版的bigNumber】
**问题原因:**可看这个https://juejin.cn/post/7216917459009536060

// Demo 1 - 乘法异常
console.log(18.9 * 100+"") // 1889.9999999999998
console.log(64.68 * 100+"") // 6468.000000000001// Demo 2
// 典中典
console.log((0.1 + 0.2 === 0.3)+"") // false
console.log((0.1 === 0.1)+"") // true....等等还有其它的例子
```typescript## 4.2 Boolean类型
boolean类型由true和false两个逻辑值组成。  
通常在条件语句中使用boolean类型的变量:
```typescript
let isDone: boolean = false;
// ...
if (isDone) {console.log ('Done!');
}

4.3 String 类型

string代表字符序列;可以使用转义字符来表示字符。
字符串字面量由单引号(')或双引号(")之间括起来的零个或多个字符组成。字符串字面量还有一特殊形式,是用反向单引号(`)括起来的模板字面量。

let s1 = 'Hello, world!\n';
let s2 = 'this is a string';
let a = 'Success';
let s3 = `The result is ${a}`;//这里的${} 是ES6 中的模板字符串,和Kotlin中字符串的${}功能一样

4.4 Object类型

  Object类型是所有引用类型的基类型。任何值,包括基本类型的值(它们会被自动装箱),都可以直接被赋给Object类型的变量。
在ArkTs中,不管你是一个普通的对象,还是一个数组,元组,集合等等,都是一个对象类型。

let str = new String()
let obj: object = strlet test = new Object()
let numberArray = [1, 2, 3, 4, 5]
let numberArrayObj = new Array<number>()
let tuple: [string, number] = ["age", 10]
let map = new Map<string, number>()
console.log("当前数据类型1:" + typeof test)//object
console.log("当前数据类型2:" + typeof numberArray)//object
console.log("当前数据类型3:" + typeof numberArrayObj)//object
console.log("当前数据类型4:" + typeof tuple)//object
console.log("当前数据类型5:" + typeof map)//object

4.5 Array类型

array,即数组,是由可赋值给数组声明中指定的元素类型的数据组成的对象。
数组可由数组复合字面量(即用方括号括起来的零个或多个表达式的列表,其中每个表达式为数组中的一个元素)来赋值。数组的长度由数组中元素的个数来确定。数组中第一个元素的索引为0。
数组有两种声明方式,一种是使用Array对象,一种直接使用中括号[]。

let array = Array<number>()let arr = []//默认值
let arr2 = [1, 2, 3, 4, 5]let array2 = Array<number>(1, 2, 3, 4, 5)//注意:数组如果没声明类型,它在JS/TS中可以并存多种类型数据的let arr = [1, "字符串", true, new Object()]
let array = Array<Object>(1, "字符串", true, new Object())

4.6 Tuple类型

Tuple Type(中文翻译:元组类型),可以认为是一个有顺序的数组类型。有以下特点:

  1. 可以明确知道包含了多少元素(这里的元素是类型)
  2. 可以明确知道每个类型所在的位置
  3. 长度固定,元组类型的变量需要为每一个位置定义对应类型的值
let tuple1: [string, number] = ["hello", 10]; // 正确
let tuple2: [string, number] = [10, "hello"]; // 错误

4.7 Enum类型

enum类型,又称枚举类型,是预先定义的一组命名值的值类型,其中命名值又称为枚举常量。
使用枚举常量时必须以枚举类型名称为前缀。默认情况下,从0开始为元素编号。当然也可以更改默认的值。如下红绿蓝

enum ColorSet { Red, Green, Blue }
console.log(typeof ColorSet.Red)//number
console.log(ColorSet.Red.toString())//0
console.log(ColorSet.Green.toString())//1

常量表达式可以用于显式设置枚举常量的值。

enum ColorSet { Red = '红色', Green = '绿色', Blue = '蓝色'}
console.log(typeof ColorSet.Red)//string
console.log(ColorSet.Red.toString())//红色
console.log(ColorSet.Green.toString())//绿色
console.log(ColorSet.Blue.toString())//蓝色

4.8 Union类型

union类型,即联合类型,是由多个类型组合成的引用类型。联合类型包含了变量可能的所有类型。

//输入值可是多种类型
function getParamsType(params?: String | Number): string {return typeof params
}console.log(getParamsType("姓名"))//string
console.log(getParamsType(18))//number//返回值可是多种类型
function getParamsType(params?: String | Number): string | boolean {if (params == "1") {return true} else {return "你好"}
}console.log(getParamsType()+"")//你好
console.log(getParamsType(1)+"")//true
console.log(getParamsType(2)+"")//你好

4.9 Undefined类型

undefined 类型只包含一个值undefined,表示未定义(即还未给出定义,以后可能会有定义)。

class Person {name?: Stringconstructor(name?: String) {this.name = name;}
}
//未赋值的情况
let p = new Person();
console.log(p?.name?.toString())//输出undefined//赋值的情况
let p = new Person("葫芦娃");
console.log(p?.name?.toString())//输出葫芦娃

4.10 Null类型

null 类型也只包含一个值null,表示为空(即此处没有值)。

class Person {name?: String | null = null
}let p = new Person();
if (p.name === undefined) {console.log("这里是 undefined")
} else if (p.name === null) {console.log("这里是 null")//会输出这一行
} else {console.log("这里是 string")
}

4.11 Aliases类型[类型别名]

Aliases类型为匿名类型(数组、函数、对象字面量或联合类型)提供名称,或为已有类型提供替代名称。

type Matrix = number[][];//声明数组
type Handler = (s: string, no: number) => string;//声明函数
type Predicate <T> = (x: T) => Boolean;//声明函数
type NullableObject = String | null;//声明联合类型//使用
class Person {name?: NullableObject = null
}

4.12 BigInt类型

Number 类型表示的是双精度浮点数,在处理大数时可能会出现精度丢失的问题。为了解决这个问题,ES11(2020)推出了BitInt类型,它可以表示大于 2^53 - 1 的整数。这原本是 Javascript 中可以用 Number 表示的最大数字。BigInt 可以表示任意大的整数。

可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数 BigInt()(但不包含 new 运算符)并传递一个整数值或字符串值。

const bigInt = BigInt(9007199254740991);
console.log(typeof bigInt)//bigint

4.13 Void类型

void类型用于指定函数没有返回值。
此类型只有一个值,同样是void。由于void是引用类型,因此它可以用于泛型类型参数。

function test1():void{
}function test2() {
}console.log(typeof test1())//undefined
console.log(typeof test2())//undefined

声明一个void类型的变量没有什么大用,因为在ArkTS你只能为它赋予undefined

let unusable: void = undefined;

4.14 Never类型

never类型表示的是那些永不存在的值的类型。 例如, never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never类型,当它们被永不为真的类型保护所约束时。

// 返回never的函数必须存在无法达到的终点
function error(message: string): never {throw new Error(message);
}// 推断的返回值类型为never
function fail() {return error("Something failed");
}// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {while (true) {}
}

5. 运算符、语句

ArkTS中的运算符和语句和主流的语言类似,这里不再赘述,详情见:运算符、语句

6. 集合类型

6.1 Array

用于存储有序的一组相同类型的元素。

6.1.1 基本API

  • concat() 用于合并两个或多个数组。
  • slice() 返回一个新数组,包含原数组中指定范围内的元素。
  • splice() 用于添加或删除数组中的元素。
  • push() 将一个或多个元素添加到数组的末尾,并返回新的长度。
  • pop() 从数组中删除最后一个元素,并返回该元素的值。
  • shift() 从数组中删除第一个元素,并返回该元素的值。
  • unshift() 将一个或多个元素添加到数组的开头,并返回新的长度。
  • reverse() 颠倒数组中元素的顺序。
  • sort() 对数组元素进行排序。
  • map() 创建一个新数组,其结果是该数组中的每个元素都调用了提供的函数后的返回值。
  • filter() 创建一个新数组,其包含通过所提供函数实现的测试的所有元素。
  • reduce() 将数组元素计算为一个值(从左到右)。
  • forEach() 对数组的每个元素执行一次提供的函数。
  • indexOf() 返回在数组中可以找到给定元素的第一个索引,如果不存在则返回 -1。
  • lastIndexOf() 返回指定元素在数组中的最后一个索引,如果不存在则返回 -1。
  • includes() 判断数组是否包含指定的值。
  • join() 将数组中的所有元素连接成一个字符串。
  • entries() 返回一个数组迭代器对象,该对象包含数组的键值对。
  • find() 返回满足提供的测试函数的第一个元素的值。
  • findIndex() 返回满足提供的测试函数的第一个元素的索引。

  • 常用的例子可以参考这篇文章:JavaScript Array 奇技淫巧

6.2 ArrayList

ArkTS 独有,参考Java实现的,使用前需要导包

import ArrayList from '@ohos.util.ArrayList';

ArrayList是一种线性数据结构,底层基于数组实现。ArrayList会根据实际需要动态调整容量,每次扩容增加50%。
ArrayList和Vector相似,都是基于数组实现。它们都可以动态调整容量,但Vector每次扩容增加1倍。
ArrayList和LinkedList相比,ArrayList的随机访问效率更高。但由于ArrayList的增删操作会影响数组内其他元素的移动,LinkedList的增加和删除操作效率更高。
推荐使用场景: 当需要频繁读取集合中的元素时,推荐使用ArrayList。

6.2.1 常见API

和Java类似,具体见https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V1/js-apis-arraylist-0000001630146253-V1

class C1 {name: string = ""age: string = ""
}
let arrayList: ArrayList<string | number | boolean | Array<number> | C1> = new ArrayList();
let result1 = arrayList.add("a");
let arrayList1: ArrayList<number> = new ArrayList();
let result2 = arrayList.add(1);
let b = [1, 2, 3];
let result3 = arrayList.add(b);
let c : C1 = {name: "Dylon", age: "13"}
let result4 = arrayList.add(c);
let result5 = arrayList.add(false);

6.3 Map

ES6 之前一般用 Object 来实现键/值存储。Map 是 ES6 新增特性,是一种新的集合类型,为这门语言带来了真正的键/值存储机制。ArkTS中也可使用该类型。

6.3.1 基本 API

  • 创建映射,new Map(),Map 构造函数也可接收一个可选的可迭代对象
  • size,使用 Map实例的 size 属性获取映射中键值对的数量
  • set(),使用 Map 实例的 set() 方法可以向应设置再添加键/值对,支持链式调用,因为 set() 方法返回 Map 实例
  • has(),查询映射是否存在指定键
  • get(),从映射中获取指定键的值
  • delete(),从映射中删除指定的键/值对
  • clear(),清除映射中的所有键/值对
// 创建一个空的 Map 实例
const m = new Map<string,string>()
// 使用 set() 方法添加键/值对
m.set('k3', 'v3').set('k4', 'v4')
console.log(m.size.toString()) // 2
console.log(m.has('k3')+"") // true
console.log(m.get('k3')+"") // v3
//遍历
m.forEach((value,key)=>{console.log(`key:${key} value:${value}`)
})
// key:k3 value:v3
// key:k4 value:v4
// keys
for (let key of m.keys()) {console.log(key)
}
// 'k3'
// 'k4'// values
for (let val of m.values()) {console.log(val)
}
// 'v3'
// 'v4'// delete、clear
console.log(m.delete('k3')+"") //true
console.log(m.has('k3')+"") // false
m.clear()
console.log(m.size.toString()) // 0

6.4 Record

泛型Record<K, V>用于将类型(键类型)的属性映射到另一个类型(值类型)。常用对象字面量来初始化该类型的值
使用场景:

  • 如果你需要表示一个具有固定结构的数据,例如一个学生的记录,其中包含姓名、年龄、成绩等字段,那么使用Record是合适的选择。
  • 如果你需要表示一个动态的、可变的数据集合,并且需要根据键来查找、插入或删除值,那么使用Map是更好的选择。例如,你可以使用Map来存储用户的偏好设置,其中键是设置的名称,值是设置的值。

6.4.1 常见API

let map: Record<string, number> = {'John': 25,'Mary': 21,
}
map['John']; // 25

6.5 HashMap

ArkTS 独有,参考Java实现的,使用前需要导包

import HashMap from '@ohos.util.HashMap'; 

HashMap底层使用数组+链表+红黑树的方式实现,查询、插入和删除的效率都很高。HashMap存储内容基于key-value的键值对映射,不能有重复的key,且一个key只能对应一个value。
HashMap和TreeMap相比,HashMap依据键的hashCode存取数据,访问速度较快。而TreeMap是有序存取,效率较低。
HashSet基于HashMap实现。HashMap的输入参数由key、value两个值组成。在HashSet中,只对value对象进行处理。
推荐使用场景: 需要快速存取、删除以及插入键值对数据时,推荐使用HashMap。

6.5.1 常见API

和Java类似,具体见 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/nonlinear-container-V5#hashset

const hashMap: HashMap<string, number> = new HashMap();
hashMap.set("squirrel", 123);
hashMap.set("sparrow", 356);
let newHashMap: HashMap<string, number> = new HashMap();
newHashMap.set("newMap", 99);
hashMap.setAll(newHashMap);

6.6 WeakMap

WeakMap(弱映射)是 ECMAScript 6 新增的集合类型,它是一种增强的键值对存储机制。是 Map 的“兄弟”类型,其 API 也是 Map 的子集。WeakMap 中的 “weak(弱)” 描述的是 JavaScript 垃圾回收程序对待“弱映射”中的键的处理方式。

6.6.1弱键

WeakMap 中的 “weak” 表示弱映射中的键是 “弱弱的拿着”。意思就是说,这些键不属于正式的引用,不会组织垃圾回收。当引用释放后对应的键值很快就会被垃圾回收。这点和 Map 不同,Map 中的对应项会编程无法直接访问的数据。

6.6.2 API

WeakMap 的 API 是 Map 的一个子集,除了以下内容之外 和 Map 没有任何区别:

  • WeakMap 的键必须是引用类型,如果提供非引用的类型的键会导致整个初始化失败
  • WeakMap 不可迭代,因为 WeakMap 中的键值对在任何时候都可能被销毁,所以没必要提供迭代能力。当然,clear() 也不存在。因为不可迭代,所以如果没有键的引用,则无法从弱映射中取的对应的值,即便代码可以访问 WeakMap 实例,也没办法取得其中的内容(Map 可以通过 迭代的方式查看)。
  • set(),使用 Map 实例的 set() 方法可以向应设置再添加键/值对,支持链式调用,因为 set() 方法返回 Map 实例
  • has(),查询映射是否存在指定键
  • get(),从映射中获取指定键的值
  • delete(),从映射中删除指定的键/值对
// 创建一个空的 Map 实例
const m = new WeakMap<String,string>()
// 使用 set() 方法添加键/值对
m.set('k3', 'v3').set('k4', 'v4')
console.log(m.has('k3')+"") // true
console.log(m.get('k3')+"") // v3
// delete、clear
console.log(m.delete('k3')+"") //true
console.log(m.has('k3')+"") // false

6.7 Set

Set(集合)是 ECMAScript 6 新的一种集合类型,一种新的集合数据结构。用于存储唯一值的集合。
Set 会维护值插入时的顺序,所以支持按顺序迭代。可以通过集合实例上的迭代器来按顺序迭代集合中的内容。
**注意:**在 TypeScript 中的 Set 集合里面, keys() 和 values() 方法返回的实际上是同一个迭代器。这是因为 Set 是一个存储唯一值的数据结构,所以键和值是同一个值。所以遍历的时候建议使用values()

6.7.1 基本 API

  • new Set(),创建集合,接收一个可选的可迭代对象作为构造函数的参数
  • ins.size,获取集合中元素的个数
  • ins.add(xx),向集合中添加新元素,返回集合实例(支持链式调用)
  • ins.has(xx),判断集合中是否存在指定元素
  • ins.delete(xx),从集合中删除指定元素,返回一个布尔值,表示集合中是否存在要删除的值
  • ins.clear(),清空集合
  • ins.keys() 方法返回一个新的迭代器对象,它包含 Set 对象中所有元素的值作为键。
  • ins.values() 方法也返回一个新的迭代器对象,它包含 Set 对象中所有元素的值。
const s = new Set(['v1', 'v2'])
console.log(s.size.toString()) // 2
s.add('v3')
console.log(s.has('v3').toString()) // truefor (const v of s.keys()) {console.log(`keys:${v}`)
}
// keys:v1
// keys:v2
// keys:v3
for (const v of s.values()) {console.log(`values:${v}`)
}
// values:v1
// values:v2
// values:v3
s.forEach((val, key) => {console.log(`key:${key} val:${val}`)
})
// key:v1 val:v1
// key:v2 val:v2
// key:v3 val:v3s.delete('v3')
console.log(s.has('v3').toString()) // false
s.clear()
console.log(s.size.toString()) // 0

6.8 HashSet

ArkTS 独有,参考Java实现的,使用前需要导包

import HashSet from '@ohos.util.HashSet';

HashSet基于HashMap实现。在HashSet中,只对value对象进行处理。
HashSet和TreeSet相比,HashSet中的数据无序存放,即存放元素的顺序和取出的顺序不一致,而TreeSet是有序存放。它们集合中的元素都不允许重复,但HashSet允许放入null值,TreeSet不建议插入空值,可能会影响排序结果。
推荐使用场景: 可以利用HashSet不重复的特性,当需要不重复的集合或需要去重某个集合的时候使用。

6.8.1 基本API

和Java类似,具体见 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/nonlinear-container-V5#hashset

6.9 WeakSet

WeakSet(弱映射)是 ECMAScript 6 新增的集合类型,它是一种增强的键值对存储机制。是 Set 的“兄弟”类型,其 API 也是 Set 的子集。WeakMap 中的 “weak(弱)” 描述的是 JavaScript 垃圾回收程序对待“弱映射”中的键的处理方式。

6.9.1 基本API

  • add(value):向集合中添加一个值。
  • delete(value):从集合中删除一个值。
  • has(value):检查集合中是否存在一个值。
// 创建一个 WeakSet
const weakSet = new WeakSet();// 创建一个对象并将其添加到 WeakSet 中
const object1 = new Object();
weakSet.add(object1);// 检查 WeakSet 中是否存在该对象
console.log(weakSet.has(object1)+""); // 输出:true// 删除该对象
weakSet.delete(object1);// 再次检查 WeakSet 中是否存在该对象
console.log(weakSet.has(object1)+""); // 输出:false

6.10 更多集合类型

还有一些不常用的集合类型,这里就不做过多说明,详情可点下方链接

  • List
  • LinkedList
  • Deque
  • Queue
  • Stack
  • TreeMap
  • TreeSet
  • LightWeightMap
  • LightWeightSet
  • PlainArray

7. 空安全

默认情况下,ArkTS中的所有类型都是不可为空的,因此类型的值不能为空。这类似于TypeScript的严格空值检查模式(strictNullChecks),但规则更严格。
在下面的示例中,所有行都会导致编译时错误:

let x: number = null;    // 编译时错误
let y: string = null;    // 编译时错误
let z: number[] = null;  // 编译时错误

可以为空值的变量定义为联合类型(Union)T | null。

let x: number | null = null;
x = 1;    // ok
x = null; // ok
if (x != null) { /* 做你想做的事 */ }

例子2
// 如果 obj 或 obj.foo 或 obj.foo.bar 为 null 或 undefined,value 将为 undefined,否则为 42

let obj = { foo: { bar: 42 } };
let value = obj?.foo?.bar; 

7.1.1 非空断言运算符 !

后缀运算符!可用于断言其操作数为非空。
应用于空值时,运算符将抛出错误。否则,值的类型将从T | null更改为T:

class C {value: number | null = 1;
}let c = new C();
let y: number;
y = c.value + 1;  // 编译时错误:无法对可空值作做加法
y = c.value! + 1; // ok,值为2//未赋值的空值属性,值为undefined
let nick: string | null
console.log(nick!)//undefined

7.1.2 空值合并运算符 ??

空值合并二元运算符??用于检查左侧表达式的求值是否等于null。如果是,则表达式的结果为右侧表达式;否则,结果为左侧表达式。
换句话说,a ?? b等价于三元运算符a != null ? a : b。
在以下示例中,getNick方法如果设置了昵称,则返回昵称;否则,返回空字符串:

class Person {// ...nick: string | null = nullgetNick(): string {return this.nick ?? '';}
}let x = null;
let y = x ?? 5; // 如果 x 为 null 或 undefined,y 将为 5,否则为 x 的值

7.1.3 空值合并赋值运算符 (??=)

用于将默认值赋给一个变量,当该变量的值为 null 或 undefined 时。如果一个变量的值为 null 或 undefined,可以使用 ??= 运算符将一个默认值赋给该变量。
**??= **运算符在日常开发中有多种使用场景:

7.1.3.1 默认参数赋值

在函数中可以使用 ??= 来为可能未传入的参数提供默认值:

function greet(name) {name ??= 'Guest';console.log(`Hello, ${name}!`);//hello Guest
}class AppConfig {theme: string = 'dark';notifications?: stringfontSize?: number
}let appConfig = new AppConfig()
console.log(JSON.stringify(appConfig))//输出:{"theme":"dark"}// 确保所有配置项都有默认值
appConfig.theme ??= 'light'; // 已经有值,所以保持不变
appConfig.notifications ??= "你好"; // 之前是 undefined,现在赋值为 你好
appConfig.fontSize ??= 14; // 之前是 undefined,现在赋值为 14console.log(JSON.stringify(appConfig)); 
// 输出:{ theme: 'light', notifications: 你好, fontSize: 14 }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/491223.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

精彩回顾|Cocos开发者沙龙长沙站

长沙-不一样 Cocos 开发者沙龙长沙站&#xff0c;完全超出了我们的预期&#xff0c;一开始还担心没有太多人报名。最后发现&#xff0c;全场爆满&#xff0c;座无虚席。 <<< 左右滑动见更多 >>> 许多小伙伴曾反馈过&#xff0c;在以往的开发者沙龙回顾文章中…

elasticsearch设置密码访问

1 用户认证介绍 默认ES是没有设置用户认证访问的&#xff0c;所以每次访问时&#xff0c;直接调相关API就能查询和写入数据。现在做一个认证&#xff0c;只有通过认证的用户才能访问和操作ES。 2 开启加密设置 1.生成证书文件 /usr/share/elasticsearch/bin/elasticsearch-…

docker安装Elasticsearch和Kibana

上传文件 加载tar包 安装 1.安装elasticsearch 通过下面的Docker命令即可安装单机版本的elasticsearch&#xff1a; docker run -d \--name es \-e "ES_JAVA_OPTS-Xms512m -Xmx512m" \-e "discovery.typesingle-node" \-v es-data:/usr/share/elastics…

Ubuntu 20.04 24.04 双网卡 Bond 配置指南

前言&#xff1a;在现代服务器管理中&#xff0c;网络的稳定性和可靠性至关重要。为了提高网络的冗余性和负载能力&#xff0c;我们经常需要配置多个网络接口以实现链路聚合或故障转移。Ubuntu系统自17.10版本起&#xff0c;引入了Netplan作为新的网络配置抽象化工具&#xff0…

热更新解决方案3 —— xLua

概述 xLua框架导入和AB包相关准备 xLua导入 其它的导入 C#调用Lua 1.Lua解析器 using System.Collections; using System.Collections.Generic; using UnityEngine; //引用命名空间 using XLua;public class Lesson1_LuaEnv : MonoBehaviour {// Start is called before the fi…

【日常笔记】Spring boot:编写 Content type = ‘text/plain‘ 接口

一、项目场景&#xff1a; 接口&#xff1a;Context-Type&#xff1a;text/plain 方式&#xff1a;POST 项目场景&#xff1a;硬件回调接口 二、实战 PostMapping(value "/xx/xxx", consumes "text/plain" ) 2.1、接口 /*** return String* time 202…

光伏智能巡检

无人值守光伏巡检解决方案 1.任务制定 规划巡检任务&#xff0c;定时执行&#xff0c;自动放飞、收纳、充电&#xff0c;随时待命 2.自动起飞、巡航 无人机按照既定巡检任务&#xff0c;自主作业&#xff0c;多场景自适应&#xff0c;航飞视频实况直播。 3.智能分析 对无人…

【Isaac Lab】Ubuntu22.04安装英伟达驱动

目录 1.1 禁用nouveau驱动 1.2 安装必要的依赖项 1.3 下载安装 1.4 查看是否安装成功 1.5 安装CUDA 1.5.1 下载 1.5.2 按照提示进行下载安装 1.5.3 添加环境变量 1.5.4 测试CUDA是否安装成功 1.1 禁用nouveau驱动 输入以下命令打开blacklist.conf文件 sudo vim /etc…

深入C语言文件操作:从库函数到系统调用

引言 文件操作是编程中不可或缺的一部分&#xff0c;尤其在C语言中&#xff0c;文件操作不仅是处理数据的基本手段&#xff0c;也是连接程序与外部世界的重要桥梁。C语言提供了丰富的库函数来处理文件&#xff0c;如 fopen、fclose、fread、fwrite 等。然而&#xff0c;这些库…

Word2Vec 模型 PyTorch 实现并复现论文中的数据集

详细注解链接&#xff1a;https://www.orzzz.net/directory/codes/Word2Vec/index.html 欢迎咨询&#xff01;

Vue中纯前端实现导出简单Excel表格的功能

Vue 前端Excel导出 Vue中纯前端导出简单Excel表格的方法(使用vue-json-excel插件) 前言 在许多的后台系统中少不了导出Excel表格的功能&#xff0c;在项目中纯前端使用vue-json-excel插件来实现简单Excel表格的导出功能。 使用方法 1、安装依赖 npm install vue-json-exc…

「数据结构详解·十五」树状数组

「数据结构详解一」树的初步「数据结构详解二」二叉树的初步「数据结构详解三」栈「数据结构详解四」队列「数据结构详解五」链表「数据结构详解六」哈希表「数据结构详解七」并查集的初步「数据结构详解八」带权并查集 & 扩展域并查集「数据结构详解九」图的初步「数据结构…

复合机器人为生产提供精准的建议和决策支持

在现代化生产的浪潮中&#xff0c;智能复合机器人以其卓越的性能和高度智能化特点&#xff0c;正成为保障生产安全与可靠性的重要力量。 智能复合机器人具备精确的感知、判断和决策能力&#xff0c;能够在复杂的生产环境中自主导航、精确操作&#xff0c;避免了人为因素可能导致…

实现按键按下(低电平)检测到下降沿

按照流程进行编程 步骤1&#xff1a; 初始化函数 包括时基工作参数配置 输入通道配置 更新中断使能 使能捕获、捕获中断及计数器 HAL_TIM_IC_Init(&ic_handle) //时基参数配置 HAL_TIM_IC_ConfigChannel(&ic_handle,&ic_config,TIM_CHANNEL_2) //输…

软件开发中的三层结构

一、三层结构概述 在软件开发中&#xff0c;三层结构&#xff08;Three - Tier Architecture&#xff09;是一种常见的软件架构模式。它将软件系统分为三个主要的层次&#xff0c;即表示层&#xff08;Presentation Layer&#xff09;、业务逻辑层&#xff08;Business Logic L…

【MQ】大白话告诉你什么是MQ,没有比这还详细还易懂的文章了吧,以RabbitMQ为例,从小白到大神

目录 分布式系统通信方式 MQ选型与应用场景 应用场景&#xff08;优势&#xff09; RabbitMQ工作模型 RabbitMQ简介 RabbitMQ 工作模型&#xff08;流程&#xff09;​编辑 Docker安装配置RabbitMQ RabbitMQ管理控制台 RabbitMQ 简单模式构建生产者 RabbitMQ 简单模式…

RTMP推流平台EasyDSS在无人机推流直播安防监控中的创新应用

无人机与低空经济的关系密切&#xff0c;并且正在快速发展。2024年中国低空经济行业市场规模达到5800亿元&#xff0c;其中低空制造产业占整个低空经济产业的88%。预计未来五年复合增速将达到16.03%。 随着科技的飞速发展&#xff0c;公共安防关乎每一个市民的生命财产安全。在…

PCIE概述

PCIE概述 文章目录 PCIE概述前言一、应用场景二、PCIE理论2.1 硬件2.2 拓扑结构&#xff1a;处理器和设备之间的关系2.3 速率2.4 层次接口2.5 四种请求类型2.5.1 bar空间2.5.2 memory2.5.3 IO2.5.4 configuration2.5.5 message 前言 参考链接&#xff1a; pcie总线知识点解析 …

SpringBoot SPI

参考 https://blog.csdn.net/Peelarmy/article/details/106872570 https://javaguide.cn/java/basis/spi.html#%E4%BD%95%E8%B0%93-spi SPI SPI(service provider interface)是JDK提供的服务发现机制。以JDBC为例&#xff0c;JDK提供JDBC接口&#xff0c;在包java.sql.*。MY…

超详细!Jmeter性能测试

前言 性能测试是一个全栈工程师/架构师必会的技能之一&#xff0c;只有学会性能测试&#xff0c;才能根据得到的测试报告进行分析&#xff0c;找到系统性能的瓶颈所在&#xff0c;而这也是优化架构设计中重要的依据。 测试流程&#xff1a; 需求分析→环境搭建→测试计划→脚…