赞
踩
前言:
目前流行的编程语言TypeScript是在JavaScript基础上通过添加类型定义扩展而来的,而ArkTS则是TypeScript的进一步扩展。TypeScript深受开发者的喜爱,因为它提供了一种更结构化的JavaScript编码方法。ArkTS旨在保持TypeScript的大部分语法,为现有的TypeScript开发者实现无缝过渡,让移动开发者快速上手ArkTS。
ArkTS比typeScipt更严格,它的一大特性是它专注于低运行时开销。ArkTS对TypeScript的动态类型特性施加了更严格的限制,以减少运行时开销,提高执行效率。通过取消动态类型特性,ArkTS代码能更有效地被运行前编译和优化,从而实现更快的应用启动和更低的功耗。
ArkTS通过声明引入变量、常量、函数和类型。
变量声明
以关键字let开头的声明引入变量,该变量在程序执行期间可以具有不同的值。
常量声明
以关键字const开头的声明引入只读常量,该常量只能被赋值一次。
对常量重新赋值会造成编译时错误。
自动类型推断
由于ArkTS是一种静态类型语言,所有数据的类型都必须在编译时确定。
但是,如果一个变量或常量的声明包含了初始值,那么开发者就不需要显式指定其类型。ArkTS规范中列举了所有允许自动推断类型的场景。
以下示例中,两条声明语句都是有效的,两个变量都是string类型:
Number类型
ArkTS提供number和Number类型,任何整数和浮点数都可以被赋给此类型的变量。
数字字面量包括整数字面量和十进制浮点数字面量。
整数字面量包括以下类别:
浮点字面量包括以下:
示例:
Boolean类型
boolean类型由true和false两个逻辑值组成。
通常在条件语句中使用boolean类型的变量:
String类型
string代表字符序列;可以使用转义字符来表示字符。
字符串字面量由单引号(')或双引号(")之间括起来的零个或多个字符组成。字符串字面量还有一特殊形式,是用反向单引号(`)括起来的模板字面量。
Void类型
void类型用于指定函数没有返回值。
此类型只有一个值,同样是void。由于void是引用类型,因此它可以用于泛型类型参数。
Object类型
Object类型是所有引用类型的基类型。任何值,包括基本类型的值(它们会被自动装箱),都可以直接被赋给Object类型的变量。
Array类型
array,即数组,是由可赋值给数组声明中指定的元素类型的数据组成的对象。
数组可由数组复合字面量(即用方括号括起来的零个或多个表达式的列表,其中每个表达式为数组中的一个元素)来赋值。数组的长度由数组中元素的个数来确定。数组中第一个元素的索引为0。
以下示例将创建包含三个元素的数组:
Enum类型
enum类型,又称枚举类型,是预先定义的一组命名值的值类型,其中命名值又称为枚举常量。
使用枚举常量时必须以枚举类型名称为前缀。
常量表达式可以用于显式设置枚举常量的值。
Union类型
union类型,即联合类型,是由多个类型组合成的引用类型。联合类型包含了变量可能的所有类型。
可以用不同的机制获取联合类型中特定类型的值。
示例:
Aliases类型
Aliases类型为匿名类型(数组、函数、对象字面量或联合类型)提供名称,或为已有类型提供替代名称。
赋值运算符
赋值运算符=,使用方式如x=y。
复合赋值运算符将赋值与运算符组合在一起,其中x op = y等于x = x op y。
复合赋值运算符列举如下:+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、|=、^=。
比较运算符
运算符 | 说明 |
---|---|
== | 如果两个操作数相等,则返回true。 |
!= | 如果两个操作数不相等,则返回true。 |
> | 如果左操作数大于右操作数,则返回true。 |
>= | 如果左操作数大于或等于右操作数,则返回true。 |
< | 如果左操作数小于右操作数,则返回true。 |
<= | 如果左操作数小于或等于右操作数,则返回true。 |
算术运算符
一元运算符为-、+、--、++。
二元运算符列举如下:
运算符 | 说明 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 除法后余数 |
位运算符
运算符 | 说明 |
---|---|
a & b | 按位与:如果两个操作数的对应位都为1,则将这个位设置为1,否则设置为0。 |
a | b | 按位或:如果两个操作数的相应位中至少有一个为1,则将这个位设置为1,否则设置为0。 |
a ^ b | 按位异或:如果两个操作数的对应位不同,则将这个位设置为1,否则设置为0。 |
~ a | 按位非:反转操作数的位。 |
a << b | 左移:将a的二进制表示向左移b位。 |
a >> b | 算术右移:将a的二进制表示向右移b位,带符号扩展。 |
a >>> b | 逻辑右移:将a的二进制表示向右移b位,左边补0。 |
逻辑运算符
运算符 | 说明 |
---|---|
a && b | 逻辑与 |
a || b | 逻辑或 |
! a | 逻辑非 |
If语句
if语句用于需要根据逻辑条件执行不同语句的场景。当逻辑条件为真时,执行对应的一组语句,否则执行另一组语句(如果有的话)。
else部分也可能包含if语句。
if语句如下所示:
条件表达式可以是任何类型。但是对于boolean以外的类型,会进行隐式类型转换:
Switch语句
使用switch语句来执行与switch表达式值匹配的代码块。
switch语句如下所示:
如果switch表达式的值等于某个label的值,则执行相应的语句。
如果没有任何一个label值与表达式值相匹配,并且switch具有default子句,那么程序会执行default子句对应的代码块。
break语句(可选的)允许跳出switch语句并继续执行switch语句之后的语句。
如果没有break语句,则执行switch中的下一个label对应的代码块。
条件表达式
条件表达式由第一个表达式的布尔值来决定返回其它两个表达式中的哪一个。
示例如下:
如果condition的为真值(转换后为true的值),则使用expression1作为该表达式的结果;否则,使用expression2。
示例:
For语句
for语句会被重复执行,直到循环退出语句值为false。
for语句如下所示:
for语句的执行流程如下:
1、 执行init表达式(如有)。此表达式通常初始化一个或多个循环计数器。
2、 计算condition。如果它为真值(转换后为true的值),则执行循环主体的语句。如果它为假值(转换后为false的值),则for循环终止。
3、 执行循环主体的语句。
4、 如果有update表达式,则执行该表达式。
5、 回到步骤2。
示例:
For-of语句
使用for-of语句可遍历数组或字符串。示例如下:
示例:
While语句
只要condition为真值(转换后为true的值),while语句就会执行statements语句。示例如下:
示例:
Do-while语句
如果condition的值为真值(转换后为true的值),那么statements语句会重复执行。示例如下:
示例:
Break语句
使用break语句可以终止循环语句或switch。
示例:
如果break语句后带有标识符,则将控制流转移到该标识符所包含的语句块之外。
示例:
Continue语句
continue语句会停止当前循环迭代的执行,并将控制传递给下一个迭代。
示例:
Throw和Try语句
throw语句用于抛出异常或错误:
try语句用于捕获和处理异常或错误:
下面的示例中throw和try语句用于处理除数为0的错误:
支持finally语句:
函数声明引入一个函数,包含其名称、参数列表、返回类型和函数体。
以下示例是一个简单的函数,包含两个string类型的参数,返回类型为string:
在函数声明中,必须为每个参数标记类型。如果参数为可选参数,那么允许在调用函数时省略该参数。函数的最后一个参数可以是rest参数。
可选参数的格式可为name?: Type。
可选参数的另一种形式为设置的参数默认值。如果在函数调用中这个参数被省略了,则会使用此参数的默认值作为实参。
函数的最后一个参数可以是rest参数。使用rest参数时,允许函数或方法接受任意数量的实参。
如果可以从函数体内推断出函数返回类型,则可在函数声明中省略标注返回类型。
不需要返回值的函数的返回类型可以显式指定为void或省略标注。这类函数不需要返回语句。
以下示例中两种函数声明方式都是有效的:
函数中定义的变量和其他实例仅可以在函数内部访问,不能从外部访问。
如果函数中定义的变量与外部作用域中已有实例同名,则函数内的局部变量定义将覆盖外部定义。
调用函数以执行其函数体,实参值会赋值给函数的形参。
如果函数定义如下:
则此函数的调用需要包含两个string类型的参数:
函数类型通常用于定义回调:
函数可以定义为箭头函数,例如:
箭头函数的返回类型可以省略;省略时,返回类型通过函数体推断。
表达式可以指定为箭头函数,使表达更简短,因此以下两种表达方式是等价的:
闭包是由函数及声明该函数的环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。
在下例中,z是执行f时创建的g箭头函数实例的引用。g的实例维持了对它的环境的引用(变量count存在其中)。因此,当z被调用时,变量count仍可用。
我们可以通过编写重载,指定函数的不同调用方式。具体方法为,为同一个函数写入多个同名但签名不同的函数头,函数实现紧随其后。
不允许重载函数有相同的名字以及参数列表,否则将会编译报错。
类声明引入一个新类型,并定义其字段、方法和构造函数。
在以下示例中,定义了Person类,该类具有字段name和surname、构造函数和方法fullName:
定义类后,可以使用关键字new创建实例:
或者,可以使用对象字面量创建实例:
字段是直接在类中声明的某种类型的变量。
类可以具有实例字段或者静态字段。
实例字段
实例字段存在于类的每个实例上。每个实例都有自己的实例字段集合。
要访问实例字段,需要使用类的实例。
静态字段
使用关键字static将字段声明为静态。静态字段属于类本身,类的所有实例共享一个静态字段。
要访问静态字段,需要使用类名:
字段初始化
为了减少运行时的错误和获得更好的执行性能,
ArkTS要求所有字段在声明时或者构造函数中显式初始化。这和标准TS中的strictPropertyInitialization模式一样。
以下代码是在ArkTS中不合法的代码。
在ArkTS中,应该这样写代码。
接下来的代码展示了如果name的值可以是undefined,那么应该如何写代码。
getter和setter
setter和getter可用于提供对对象属性的受控访问。
在以下示例中,setter用于禁止将age属性设置为无效值:
在类中可以定义getter或者setter。
方法属于类。类可以定义实例方法或者静态方法。静态方法属于类本身,只能访问静态字段。而实例方法既可以访问静态字段,也可以访问实例字段,包括类的私有字段。
实例方法
以下示例说明了实例方法的工作原理。
calculateArea方法通过将高度乘以宽度来计算矩形的面积:
必须通过类的实例调用实例方法:
静态方法
使用关键字static将方法声明为静态。静态方法属于类本身,只能访问静态字段。
静态方法定义了类作为一个整体的公共行为。
必须通过类名调用静态方法:
继承
一个类可以继承另一个类(称为基类),并使用以下语法实现多个接口:
继承类继承基类的字段和方法,但不继承构造函数。继承类可以新增定义字段和方法,也可以覆盖其基类定义的方法。
基类也称为“父类”或“超类”。继承类也称为“派生类”或“子类”。
示例:
包含implements子句的类必须实现列出的接口中定义的所有方法,但使用默认实现定义的方法除外。
父类访问
关键字super可用于访问父类的实例字段、实例方法和构造函数。在实现子类功能时,可以通过该关键字从父类中获取所需接口:
方法重写
子类可以重写其父类中定义的方法的实现。重写的方法必须具有与原始方法相同的参数类型和相同或派生的返回类型。
方法重载签名
通过重载签名,指定方法的不同调用。具体方法为,为同一个方法写入多个同名但签名不同的方法头,方法实现紧随其后。
如果两个重载签名的名称和参数列表均相同,则为错误。
类声明可以包含用于初始化对象状态的构造函数。
构造函数定义如下:
如果未定义构造函数,则会自动创建具有空参数列表的默认构造函数,例如:
在这种情况下,默认构造函数使用字段类型的默认值来初始化实例中的字段。
派生类的构造函数
构造函数函数体的第一条语句可以使用关键字super来显式调用直接父类的构造函数。
构造函数重载签名
我们可以通过编写重载签名,指定构造函数的不同调用方式。具体方法为,为同一个构造函数写入多个同名但签名不同的构造函数头,构造函数实现紧随其后。
如果两个重载签名的名称和参数列表均相同,则为错误。
类的方法和属性都可以使用可见性修饰符。
可见性修饰符包括:private、protected和public。默认可见性为public。
Public(公有)
public修饰的类成员(字段、方法、构造函数)在程序的任何可访问该类的地方都是可见的。
Private(私有)
private修饰的成员不能在声明该成员的类之外访问,例如:
Protected(受保护)
protected修饰符的作用与private修饰符非常相似,不同点是protected修饰的成员允许在派生类中访问,例如:
对象字面量是一个表达式,可用于创建类实例并提供一些初始值。它在某些情况下更方便,可以用来代替new表达式。
对象字面量的表示方式是:封闭在花括号对({})中的'属性名:值'的列表。
ArkTS是静态类型语言,如上述示例所示,对象字面量只能在可以推导出该字面量类型的上下文中使用。其他正确的例子:
也可以在数组元素类型或类字段类型中使用:
Record类型的对象字面量
泛型Record<K, V>用于将类型(键类型)的属性映射到另一个类型(值类型)。常用对象字面量来初始化该类型的值:
类型K可以是字符串类型或数值类型,而V可以是任何类型。
接口声明引入新类型。接口是定义代码协定的常见方式。
任何一个类的实例只要实现了特定接口,就可以通过该接口实现多态。
接口通常包含属性和方法的声明
示例:
实现接口的类示例:
接口属性可以是字段、getter、setter或getter和setter组合的形式。
属性字段只是getter/setter对的便捷写法。以下表达方式是等价的:
实现接口的类也可以使用以下两种方式:
接口可以继承其他接口,如下面的示例所示:
继承接口包含被继承接口的所有属性和方法,还可以添加自己的属性和方法。
泛型类型和函数允许创建的代码在各种类型上运行,而不仅支持单一类型。
类和接口可以定义为泛型,将参数添加到类型定义中,如以下示例中的类型参数Element:
要使用类型CustomStack,必须为每个类型参数指定类型实参:
编译器在使用泛型类型和函数时会确保类型安全。参见以下示例:
泛型类型的类型参数可以被限制只能取某些特定的值。例如,MyHashMap<Key, Value>这个类中的Key类型参数必须具有hash方法。
在上面的例子中,Key类型扩展了Hashable,Hashable接口的所有方法都可以为key调用。
使用泛型函数可编写更通用的代码。比如返回数组最后一个元素的函数:
如果需要为任何数组定义相同的函数,使用类型参数将该函数定义为泛型:
现在,该函数可以与任何数组一起使用。
在函数调用中,类型实参可以显式或隐式设置:
泛型类型的类型参数可以设置默认值。这样可以不指定实际的类型实参,而只使用泛型类型名称。下面的示例展示了类和函数的这一点。
默认情况下,ArkTS中的所有类型都是不可为空的,因此类型的值不能为空。这类似于TypeScript的严格空值检查模式(strictNullChecks),但规则更严格。
在下面的示例中,所有行都会导致编译时错误:
可以为空值的变量定义为联合类型T | null。
后缀运算符!可用于断言其操作数为非空。
应用于空值时,运算符将抛出错误。否则,值的类型将从T | null更改为T:
空值合并二元运算符??用于检查左侧表达式的求值是否等于null或者undefined。如果是,则表达式的结果为右侧表达式;否则,结果为左侧表达式。
换句话说,a ?? b等价于三元运算符(a != null && a != undefined) ? a : b。
在以下示例中,getNick方法如果设置了昵称,则返回昵称;否则,返回空字符串:
在访问对象属性时,如果该属性是undefined或者null,可选链运算符会返回undefined。
说明:getSpouseNick的返回类型必须为string | null | undefined,因为该方法可能返回null或者undefined。
可选链可以任意长,可以包含任意数量的?.运算符。
在以下示例中,如果一个Person的实例有不为空的spouse属性,且spouse有不为空的nick属性,则输出spouse.nick。否则,输出undefined:
程序可划分为多组编译单元或模块。
每个模块都有其自己的作用域,即,在模块中创建的任何声明(变量、函数、类等)在该模块之外都不可见,除非它们被显式导出。
与此相对,从另一个模块导出的变量、函数、类、接口等必须首先导入到模块中。
可以使用关键字export导出顶层的声明。
未导出的声明名称被视为私有名称,只能在声明该名称的模块中使用。
注意:通过export方式导出,在导入时要加{}。
静态导入
导入声明用于导入从其他模块导出的实体,并在当前模块中提供其绑定。导入声明由两部分组成:
导入绑定可以有几种形式。
假设模块具有路径“./utils”和导出实体“X”和“Y”。
导入绑定* as A表示绑定名称“A”,通过A.name可访问从导入路径指定的模块导出的所有实体:
导入绑定{ ident1, ..., identN }表示将导出的实体与指定名称绑定,该名称可以用作简单名称:
如果标识符列表定义了ident as alias,则实体ident将绑定在名称alias下:
动态导入
应用开发的有些场景中,如果希望根据条件导入模块或者按需导入模块,可以使用动态导入代替静态导入。
import()语法通常称为动态导入dynamic import,是一种类似函数的表达式,用来动态导入模块。以这种方式调用,将返回一个promise。
如下例所示,import(modulePath)可以加载模块并返回一个promise,该promise resolve为一个包含其所有导出的模块对象。该表达式可以在代码中的任意位置调用。
如果在异步函数中,可以使用let module = await import(modulePath)。
那么,可以像下面这样进行动态导入:
更多的使用动态import的业务场景和使用实例见动态import。
导入HarmonyOS SDK的开放能力
HarmonyOS SDK提供的开放能力(接口)也需要在导入声明后使用。可直接导入接口模块来使用该模块内的所有接口能力,例如:
从HarmonyOS NEXT Developer Preview 1版本开始引入Kit概念。SDK对同一个Kit下的接口模块进行了封装,开发者在示例代码中可通过导入Kit的方式来使用Kit所包含的接口能力。其中,Kit封装的接口模块可查看SDK目录下Kit子目录中各Kit的定义。
通过导入Kit方式使用开放能力有三种方式:
方式一:导入Kit下单个模块的接口能力。例如:
方式二:导入Kit下多个模块的接口能力。例如:
方式三:导入Kit包含的所有模块的接口能力。例如:
其中,“module”为别名,可自定义,然后通过该名称调用模块的接口。
说明
方式三可能会导入过多无需使用的模块,导致编译后的HAP包太大,占用过多资源,请谨慎使用。
模块可以包含除return语句外的任何模块级语句。
如果模块包含主函数(程序入口),则模块的顶层语句将在此函数函数体之前执行。否则,这些语句将在执行模块的其他功能之前执行。
程序(应用)的入口是顶层主函数。主函数应具有空参数列表或只有string[]类型的参数。
关键字this只能在类的实例方法中使用。
示例
使用限制:
示例
关键字this的指向:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。