ArkTs语法进阶

210 阅读7分钟

一,instanceof

1.作用

instanceof 运算符可以用来检测某个对象是否是某个类的实例

2.基础用法

// 返回判断结果 **布尔值**
实例对象 instanceof Class

二,typeof运算符

1.作用

可以通过 typeof 运算符来获取类型,他返回的是一个字符串

2.基础用法

// 前面 5 个可以正常获取到类型
console.log(typeof 123) // number
console.log(typeof '123') // string
console.log(typeof false) // boolean
console.log(typeof undefined) // undefined

function func() {
}

console.log(typeof func) // function

class Person {
  name: string = 'jack'
}

// 对象 数组 null 获取到的都是 object
// 后续可以结合 instanceof 进行精确判断
const p: Person = new Person()
console.log(typeof null) // object
console.log(typeof [1, 2, 3]) // object
console.log(typeof p) // object

三,修饰符

1.作用

类的方法和属性可以通过修饰符来 限制访问

2. donly(只读)

可以用来修饰属性(字段),修饰之后外部只可以取值,无法修改

3. private(私有)

private修饰的成员不能在声明该成员的类之外访问,包括子类

4. protected(受保护)

protected修饰符的作用与private修饰符非常相似,不同点是protected修饰的成员允许在派生类(子类)中访问

5. public(公共)

public修饰的类成员(字段、方法、构造函数)在程序的任何可访问该类的地方都是可见的。

6.总结

修饰符名作用适用范围访问限制
readonly只读属性无限制
private私有属性、方法类内部可以访问
protect保护属性、方法类及子类可以访问
public公共属性、方法无限制

四,剩余参数

1.作用

通过剩余参数的语法,我们可以将 函数方法 中一个不定数量的参数表示为一个数组

2.用例模板

// **剩余参数只能写在最后一位**
function 函数名(参数1,参数2,...剩余参数数组){
  // 逻辑代码
  // 剩余参数之前的参数 挨个获取即可
  // 剩余参数:以数组的形式获取
}

3.用例实现

function sum(numA:number,numB:number,...theArgs:number[]) {
  let total = numA+numbB;
  for (const arg of theArgs) {
    total += arg;
  }
  return total;
}

console.log(sum(1, 2, 3).toString()) // 6

console.log(sum(1, 2, 3, 4).toString()) // 10

五,展开

1.用法

只能用在数组上,常用语进行数组的合并,以及将一个数组追加到一个空数组中

2.基础用法实例

const numArr1: number[] = [1, 2, 3, 4]
const numArr2: number[] = [5, 6, 7]

// 合并到一起
const totalArr: number[] = [...numArr1, ...numArr2]
//输出:1,2,3,4,5,6,7

六,简单数据类型,复杂数据类型

1.基本数据类型

number string boolean undefine null

2.复杂数据类型(引用数据类型)

Object Funnction Array

3.内存中堆栈空间

1.栈:访问速度快,存放基本数据类型

2.堆:存储容量大,用于存放引用数据类型

4.两种数据类型的存储方式

基本类型:变量名,变量值都存储在栈中,访问速度快

引用类型:变量名,内存地址存放在栈中,变量值存放在堆中

注意

class Person {
  name: string = ''

  constructor(name: string) {
    this.name = name
  }
}

const p1: Person = new Person('jack')
const p2: Person = p1
p2.name = 'rose'        
//p1,p2值为rose

七,接口补充

接口定义及实现

interface 接口1{
  属性1:类型
}
interface 接口2 extends 接口1 {
  属性2:类型
}

class 类 implements 接口{
  // 必须实现 接口中定义的**所有**属性、方法,否则会报错
}

八,泛型

1.作用

泛型在保证类型安全(不丢失类型信息)的同时,可以让函数等与多种不同的类型一起工作,灵活可复用 通俗一点就是类型是可变的!

2.泛型方式

1.泛型函数

 /* 泛型函数演示:
 * 1. 泛型函数语法:
 *    function 函数名称<T>(形参:T) {
 *      let tmp:T = 形参
 *      return [形参]   // T[]
 * }
function type<T>(args: T) {
  return [args]
}
let a=type(100)     输出:100
let b=type<boolean>(false)       输出:false
let c=type<string>('false')         输出:false
let d=type<string[]>(['false','数组'])    输出:['false','数组']
let e=type<number[]>([100,11])        输出:[100,11]

2.泛型约束

1.联合类型

// 泛型函数getData的T约束只能传入数字和字符串这两个类型的参数
function getData<T extends number | string>(args:T){
  return [args]
}

getData('ok') // ✔️
getData(100) // ✔️
getData(true) // ❌不接受布尔类型

2.枚举类型

// 约束T只能是Color枚举中的一个值
function getColor<T extends Color>(color: T) {
  return color
}

getColor(Color.White)// ✔️
getColor('White')// ❌

3.接口类型

// 定义接口
interface iPerson {
  name: string
}

// 泛型函数T被iPerson约束
function getData<T extends iPerson>(args: T) {
  return args
}

let obj: iPerson = { name: '张三' }
let arr = [1,2,3]
getData(obj)  // ✔️
getData(arr)  // ❌

3.多个泛型参数

 * 泛型函数多个参数以及多个参数的类型约束
 * 1. 多个参数语法:
 *  函数名<T1,T2,...>(参数1:T1,参数2:T2,...) {}
 *举例:
 function funA<T1, T2>(a1: T1, a2: T2) {
  console.log('a1=', a1, 'a2=', a2)
}
 *
 * 2. 多个参数类型约束语法:
 *   函数名<T1 extends 类型,T2 extends 类型,....>()
 *   函数名<T1 extends 类型,T2 ....>()
 *
 * 类型可以是:基本类型和复杂类型,联合类型,枚举
 
function type<t1 extends string,t2>(name:t1,other:t2){
  console.log(name,other)
}
type('张三',10)
type('张三','男')
type('颤三',true)

4.泛型接口


interface data<t>{
  name:string
  age:number
  date:t
}
let obj:data<Number[]>={
  name:'张三',
  age:12,
  date:[12,14]     //number[]形式
}
let obj1:data<string[]>={
  name:'三',
  age:12,
  date:['12','14']   //string[]形式
}
console.log(JSON.stringify(obj))   //输出 {"name":"张三","age":12,"date":[12,14]}
console.log(JSON.stringify(obj1))  //打印数组数据  {"name":"三","age":12,"date":["12","14"]}

九,工具类型(简化代码)

1、Partial<类型名>

作用:将必选参数的所有属性转化为可选参数

1.基础语法

type 新类型 = Partial<接口>
type 新类型 = Partial<类>

// 后续使用新类型即可

2.基础用例

class Person {
  name: string = ''
  age: number = 0
  friends: string[] = []
}

type ParPerson = Partial<Person>

// 因为都是可选的,可以设置为空对象
let p: ParPerson = {}

2.Readonly<类型>用法同上

作用:将所有可选属性方法等转化为必选属性

3.Readonly<类型>用法同上

作用:将所有属性设置为只读(只能访问,修改会报错)

4.Record<Keys,Type>

作用:构造一个对象类型,其属性键为Keys,属性值为Type。该实用程序可用于将一种类型的属性映射到另一种类型。

@State person = {'name':'张三'}  // ❌这样定义报错 -> 因为没有使用interface指定对象类型

// 如果不想定义interface,就可以直接使用Record<Key,Value>来指定对象类型即可
@State person:Record<string,string> = {'name':'张三'}  // ✔️

✨✨注意:{}对象的属性名类型要对应Record<Key类型,value类型>  中的Key类型,属性值对应value类型
console.log(person['name'].toString())  //输出张三

十,空安全

1.作用

默认情况下,ArkTS中的所有类型都是不可为空的。如果要设置为空,需要进行特殊的处理,并且在获取 可能为空的值的时候也需要特殊处理

2.联合类型设置为空

let x: number = null    // 编译时错误
let y: string = null    // 编译时错误
let z: number[] = null  // 编译时错误
解决办法:
// 通过联合类型设置为空
let x: number | null = null
x = 1    // ok
x = null // ok

3.非空断言运算符

后缀运算符! 可用于断言其操作数为非空。
应用于空值时,运算符将抛出错误。否则,值的类型将从T | null更改为T:
let x: number | null
let y: number
y = x + 1;  // 编译时错误:无法对可空值作加法
y = x! + 1; // 通过非空断言,告诉编译器 x不为 null

4.空值合并运算符

class Person {
  name: string | null = null

  getName(): string {
    // return this.name != null ? this.name : '' 
    // 等同于 如果 name不为空 就返回 name 反之返回 ''
    return this.name ?? ''
  }
}

5.可选链

作用

在访问对象属性时,如果该属性是undefined或者null,可选链运算符会返回undefined。

interface iPerson{
  name:string
  dogAge?:number  // 人有宠物狗也有可能没有宠物狗,所以狗的年龄dogAge为可选
}

 //定义人对象
let person:iPerson = {name:'明明'} 

// 打印人拥有的宠物狗年龄
console.log(person.dogAge.toString())  // 报错❌

// 解决方案1:使用if判断来判断如果为空就不执行,编译器认为这个代码安全,运行执行✔️
if(person.dogAge){
  console.log(person.dogAge.toString())
}
// 解决方案2:使用?可选链来断定可能为空,编译器认为这个代码安全,运行执行✔️
console.log(person.dogAge?.toString())