ArkTS语言简介
1.2:ArkTS语言简介
ArkTS是鸿蒙生态的应用开发语言。它在保持TypeScript(简称TS)基本语法风格的基础上,进一步通过规范强化静态检查和分析,使得在程序运行之前的开发期能检测更多错误,提升代码健壮性,并实现更好的运行性能。同时,提供了声明式UI范式、状态管理支持等相应的能力,让开发者可以以更简洁、更自然的方式开发高性能应用。
ArkTS提供了声明式UI范式、状态管理支持等相应的能力,让开发者可以以更简洁、更自然的方式开发应用。
同时,它在保持TypeScript(简称TS)基本语法风格的基础上,进一步通过规范强化静态检查和分析,使得在程序运行之前的开发期能检测更多错误,提升代码健壮性,并实现更好的运行性能。
针对JavaScript(简称JS)/TS并发能力支持有限的问题,ArkTS对并发编程API和能力进行了增强。
ArkTS支持与JS/TS高效互操作,兼容JS/TS生态。
1.2.1ArkTS设计理念
-
为更好地支持OpenHarmony/HarmonyOS应用的开发和运行,从API10版本开始,ArkTS在TS的基础上,进一步通过规范强化静态检查和分析,这样做有两个好处:
1.许多错误在编译时可以被检测出来,不用等到运行时,这大大降低了代码运行错误的风险,有利于程序的健壮性;
2.减少运行时的类型检查,从而降低了运行时负载,有助于提升执行性能。
-
ArkTS保留了TS大部分的语法特性,这可以帮助开发者更容易上手ArkTS。同时,对于已有的标准TS代码,开发者仅需对少部分代码进行ArkTS语法适配,大部分代码可以直接复用。
-
ArkTS支持与标准JS/TS的高效互操作,兼容JS/TS生态。HarmonyOS也提供了标准JS/TS的执行环境支持,在“更注重已有生态直接复用”的场景下,开发者可以选择使用标准JS/TS进行代码复用或开发,更方便兼容现有生态。
最后这些组件的底层由 C++ 实现,读者可在 ACE 仓里阅读各组件的实现源码,采用 C++ 实现的好处之一是可以方便对接其它语言的UI框架。比如华为自研的编程语言仓颉,仓颉定义一套 UI 描述框架,通过 FFI 的形式对接 ACE 的实现。
如今仓颉的发布,我们终于也有了自己的编程语言 + 编译器 + OpenHarmony/HarmonyOS,如果芯片领域取得突破(芯片架构 + 芯片制程),那么在计算机领域我们的基础底座就无惧任何打压和封锁了,相信这一天很快会到来……
UI框架的发展趋势,从 Android 和 iOS 的发展历程看,Android 从 View 框架到 Jetpack Compose,iOS 的 UIKits 到 SwiftUI,都是由命令式UI往声明式UI发展,据了解仓颉推出的UI框架底层对接的是 ACE ,也是是声明式UI框架,并且和ArkUI框架的声明式UI的语法很类似,因此本书笔者只介绍基于 TS 扩展的声明式开发方式。后面如果有需要,我们也会给大家单独更新仓颉章节。
1.2.1:什么是TS?
TypeScript 简称 TS ,它是 JavaScript 的一个超集并支持 ECMAScript 6 标准,如果读者已经熟悉 TS 语法可以直接跳过本节了,如果有过其它编程语言经验的话会很容易上手,语言都是相通的,充其量就是熟悉一下不同语言间的语法,本节只是简单介绍一下 TS 语法,如果想更多的了解 TS,请自行查看 TypeScript 官网。
1.2.2:数据类型
-
Any
TypeScript 提供了
any
关键字表示任意数据类型,声明为该类型的变量可以赋予任意类型的值。var data: any; // 声明data为any类型 data = true; console.log(typeof data); // boolean data = 'OpenHarmony'; console.log(typeof data); // string data = 100; console.log(typeof data); // number data = 10.5 console.log(typeof data); // number
-
number
TypeScript 提供了
number
关键字来表示数字类型,它是双精度 64 位浮点值,既可以表示整数,又可以表示小数。var data: number; data = 100; console.log(typeof data) // number data = -10; console.log(typeof data) // number data = 3.14; console.log(typeof data) // number data = 0b10001; console.log(typeof data) // number
-
string
TypeScript 提供了
string
关键字来表示字符串类型,使用单引号('
)或双引号("
)来表示字符串类型,也可以使用反引号(`)来定义多行文本和内嵌表达式。var data: string; data = "Hello, OpenHarmony"; data = 'Hello, OpenHarmony'; data = `Hello, ${data}` console.log(data) // Hello, Hello, OpenHarmony
-
boolean
TypeScript 提供了
boolean
关键字来表示逻辑值 true 和 false。var data: boolean = false; data = true; data = false;
-
数组类型
TypeScript 没有提供专门的关键字来表示数组类型,声明一个数组可以使用元素类型后边加 [] 或者数组泛型的方式。
var scores: number[] = [90, 88]; // 声明一个number数组 var names: string[] = ["张三", "李四"]; // 声明一个string数组 var address: Array<string> = ["Beijing", "Tianjin"]; // 声明一个string数组 console.log(names[0]) // 访问数组 console.log(scores[0].toString()) // 访问数组 console.log(address[0]) // 访问数组 for(var i = 0; i < address.length; i++) { // 遍历数组 console.log(address[i]) } for(var index in address) { // 遍历数组 console.log(address[index]) }
-
元组
TypeScript 提供了元组来表示已知元素数量和类型的数组,元组内的各元素的类型不必相同,但是对应位置的类型必须一致。
var user: [string, number, string]; // 定义一个元组 user = ["张三", 18, 'Beijing']; // 初始化元组,对应位置类型必须一致 console.log(`姓名:${user[0]}`) // 姓名:张三 console.log(`年龄:${user[1]}`) // 年龄:18 console.log(`住址:${user[2]}`) // 住址:Beijing
-
enum
TypeScript 提供了
enum
关键字表示枚举类型,枚举类型主要用于定义数值的集合。enum Color { // 定义一个枚举 Red, Green, Blue } var c: Color = Color.Blue; // 定义枚举类型 console.log(c.toString()); // 2
-
void
TypeScript 提供了
void
关键字表示函数的返回类型为空,也就是函数没有返回值。function print(msg: string): void { // 函数没有返回值 console.log(msg) }
-
undefined
TypeScript 提供了
undefined
关键字表示声明了一个变量但并没有赋值的情况。var data; // 声明了data,但是没有赋值 console.log(typeof data); // undefined
-
null
TypeScript 提供了
null
关键字表示一个对象没有初始化。class Person { } var person: Person; // 声明一个person,但是没有初始化 if(null == person) { console.log("person is null"); // person is null }
-
联合类型
TypeScript 允许通过
|
将一个变量设置成多种类型,赋值的时候可以根据设置的类型来赋值。var data: string | number; // 设置data为联合类型 data = 'OpenHarmony'; // 正确 data = 99; // 正确 data = true; // 编译报错,类型不匹配
📢:联合类型很重要,ArkUI框架里大量使用了联合类型。
1.2.3:变量声明
-
var
变量在使用前必须先声明,TS 使用
var
声明一个变量,我们可以使用一下四种方式来声明变量:-
声明变量的类型并赋值初始值,格式:var [变量名] : [类型] = 值;
var osName:string = "OpenHarmony";
-
声明变量的类型但不赋值初始值,格式:var [变量名] : [类型];
var osName:string;
-
声明变量并赋值初始值,但不设置类型,格式:var [变量名] = 值;
var osName = "OpenHarmony";
-
声明变量并没有设置类型和初始值,该类型可以是任意类型,默认值为 undefined,格式:var [变量名];
var osName;
简单样例如下:
var osName: string = "OpenHarmony"; var price1: number = 5; var price2: number = 5.5 var sum = price1 + price2 console.log("操作系统名字: " + osName); // 操作系统名字: OpenHarmony console.log("第一个价格是: " + price1); // 第一个价格是: 5 console.log("第二个价格是: " + price2); // 第二个价格是: 5.5 console.log("总价格: " + sum); // 总价格: 10.5
📢:TypeScript 遵循强类型,如果将不同的类型赋值给变量会编译错误,样例如下:
var count: number = "hello"; // 这个代码会编译错误
-
1.2.4:函数
-
函数声明
函数就是包裹在花括号中的代码块,前边使用
function
关键字,语法格式如下:function function_name() { // 执行代码 }
例如声明函数如下:
function log(msg: string) { // 声明一个函数 console.log(msg); // 代码块 }
-
函数调用
函数只有通过调用才可以执行函数内的代码,语法格式如下:
function_name()
样例如下:
function log(msg: string) { // 声明一个函数 console.log(msg); // 代码块 } log("Hello, OpenHarmony"); // 调用函数
-
函数返回值
如果希望得到函数的执行结果,可以使用
return
语句,语法如下:function function_name(): return_type { return value; // return语句 }
样例如下:
function sayHi():string { // 定义sayHi函数,该函数的返回类型为string return "Hello!" } function execute() { // 定义execute函数 var msg = sayHi(); // 调用sayHi()函数 console.log(msg); // 打印sayHi()函数的返回值 } execute(); // 调用execute()函数
-
带参数函数
在调用函数时可以向函数传递值,这些值被称为参数,语法如下:
function func_name(param1 :paramType, param2 :paramType) { }
样例如下:
function add(x: number, y: number): number { // 定义add函数,该函数返回类型为nubmer, 接收两个number类型的参数x return x + y; } console.log(add(1,2)) // 3
-
可选参数
如果函数定义了参数则必须传递这些参数否则报错,如果不想传递这些参数,可以添加
?
,语法如下:function func_name(param1: paramType, param2?: paramType) { }
样例如下:
function add(x: number, y?: number) { if (y) { return x + y; } else { return x; } } console.log(add(10).toString()); // 10 console.log(add(10, 10).toString()); // 20
📢:如果参数不全是可选参数,那么可选参数的位置必须放在最后。
-
默认参数
函数定义了参数则必须传递这些参数否则报错,如果不想传递这些参数除了使用可选参数外,也可以使用默认参数,当不传入该参数时则使用默认值,语法如下:
function func_name(param1: paramType, param2: paramType = default_value) { }
样例如下:
function add(x: number = 20, y: number = 50) { // 设置x和y的默认值 return x + y; } console.log(add(10).toString()); // 60 console.log(add(10, 10).toString()); // 20
📢:函数的参数不能同时是默认参数和可选参数。
-
剩余参数
在不确定要向函数传递多个参数的情况下,可以使用剩余参数,剩余参数前边以
...
为前缀数据类型为数组的形式提供,语法如下:function func_name(param1: paramType, param2: paramType, ...params: paramType[]) { }
样例如下所示:
function add(param1: number, param2: number, ...params: number[]) { // 剩余参数 var result = param1 + param2; for(var i = 0; i < params.length; i++) { // 遍历剩余参数 result += params[i]; } return result; } console.log(add(1, 2, 3, 4, 5).toString()); // 15
1.2.5:类
-
定义类
TypeScript 是面向对象的 JavaScript,定义一个类使用关键字
class
,类可以包含字段、构造方法和方法。语法如下:class class_name { // 类作用域 }
样例如下:
class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } info(): string { return "name: " + this.name + ", age: " + this.age; } }
-
创建类对象
类定义完后,可以通过
new
关键字实例化一个类的对象,实例化类对象即调用类的构造方法,语法如下:var object_name = new class_name([ args ])
样例如下:
var person = new Person('harmony', 10); // 创建一个Person对象
-
访问类属性和方法
访问类的属性和方法以
.
号的形式,语法如下:obj.field_name // 访问属性 obj.function_name() // 访问方法
样例如下:
var person = new Person('harmony', 10); // 创建一个person console.log(person.name); // harmony console.log(person.age.toString()); // 10 console.log(person.info()); // name: harmony, age: 10
-
类的继承
TypeScript 支持继承类,创建类的时候可以使用关键字
extends
继承一个已有的类,这个已有的类称为父类,继承它的类称为子类。子类除了不能继承父类的私有成员(方法和属性)和构造函数,其他的都可以继承。语法如下:class child_class_name extends parent_class_name { }
样例如下:
class Zhangsan extends Person { sayHello() { console.log("Hello, " + this.name) } } var person = new Zhangsan('harmony', 10); // 创建person console.log(person.name); // harmony console.log(person.age.toString()); // 10 console.log(person.info()); // name: harmony, age: 10
📢:类的继承只支持单继承,不支持多继承。也就是说子类只能继承一个父类。
-
方法重写
子类可以重写父类的方法,在重写父类方法的时候也可以使用
super
关键字调用父类的方法。样例如下:class Zhangsan extends Person { info(): string { // 重写父类方法 console.log(super.info()); // 调用父类方法 return "Hello, " + this.name; // 重新实现info方法 } } var person = new Zhangsan('harmony', 10); console.log(person.name); // harmony console.log(person.age.toString()); // 10 console.log(person.info()); // name: harmony, age: 10 // Hello, harmony
-
访问修饰符
TypeScript 中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。TypeScript 支持 3 种不同的访问权限。
-
public(默认):公有,可以在任何地方被访问。
-
protected:受保护,可以被其自身以及其子类访问。
-
private:私有,只能被其定义所在的类访问。
样例如下所示:
class Person { name: string; private age: number; // age为private,外界无法访问 constructor(name: string, age: number) { this.name = name; this.age = age; } info(): string { return "name: " + this.name + ", age: " + this.age; } } var person = new Person('harmony', 10); console.log(person.name); // harmony console.log(person.age.toString()); // 编译报错,age为private
-
1.2.6:接口
-
定义接口
接口是一系列抽象方法的声明,接口定义后需要具体的类实现,语法如下:
interface interface_name { // 抽象方法 }
样例如下:
interface IPerson { // 定义一个接口 name: string; // 定义接口的一个属性 say: () => string; // 定义接口的一个方法 } var person: IPerson = { // 创建一个接口的实例 name: "OpenHarmony", // 设置属性值 say: () => { // 实现接口方法 return "Hello, " + person.name; } } console.log(person.name); // OpenHarmony console.log(person.say()); // Hello, OpenHarmony
-
接口继承
接口可以使用
extends
关键字继承其它接口来扩展自己,接口既支持单继承又支持多继承,多继承时接口间使用逗号,
分隔。语法如下:// 接口单继承 interface Child_interface_name extends super_interface_name { } // 接口多继承 interface Child_interface_name extends super_interface_name1, super_interface_name2 { }
样例如下:
interface IPerson { // 定义接口IPerson name: string; say: () => string; } interface ITeacher extends IPerson { // 定义接口ITeacher并继承IPerson age: number; teach: () => void; } var teacher = <ITeacher>{}; teacher.name = "张三"; teacher.age = 18; teacher.say = () => { return "你好,我是" + teacher.name; } teacher.teach = () => { console.log("同学们好,我们开始上课啦") } console.log("name: " + teacher.name); console.log("age : " + teacher.age); console.log("say :" + teacher.say()); teacher.teach();
-
类实现接口
类可以使用
implements
关键字实现一个接口,一个类实现接口后必须声明和实现接口的所有属性和方法。interface IPerson { // 定义一个接口 name: string; // 定义接口的属性 say: () => string; // 定义接口的方法 } class Person implements IPerson { // 类型实现接口 name: string; // 必须声明接口属性 constructor(name: string) { // 在构造方法对属性初始化 this.name = name; } say(): string { // 实现接口的方法 return `Hello, I'm ${this.name}`; } } class Teacher implements IPerson { // 类型实现接口 constructor(public name: string) { // 声明接口属性简化方式 } say(): string { // 实现接口的方法 return `Hello, I'm ${this.name}`; } } var person: IPerson = new Person("王大爷"); // 创建IPerson实现类 console.log(person.say()); // Hello, I'm 王大爷 console.log(person.name); // 王大爷 person = new Teacher("王老师"); // 创建IPerson实现类 console.log(person.say()); // Hello, I'm 王老师 console.log(person.name); // 王老师
1.2.7:小结
本节简单介绍了 TS 基础语法部分,掌握这些基础部分可以支撑日常简单应用开发了,对于 TS 的高级部分读者请参考官网。
当然同时也推荐大家关注下面几篇文章。
1.2.8参考
备注
作者:灰太狼,夏天
來源:坚果派 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。负责追究相关责任。