本文地址
目錄
- 目錄
- 鴻蒙 ArkTS 基礎語法
- 型別
- 運算子
- 語句
- 函式
- 類
- 介面
- 泛型
- 空安全
- 模組匯入匯出
鴻蒙 ArkTS 基礎語法
官方文件
型別
以關鍵字let
宣告引入變數,以關鍵字const
宣告引入只讀常量
let hi: string = 'hello';
const hello: string = 'hello';
ArkTS提供number
和Number
型別,任何整數和浮點數都可以被賦給此型別的變數。
string
代表字元序列;可以使用跳脫字元來表示字元。可以使用單引號'
或雙引號"
或反引號。只有反引號支援字串模板,
let s1 = 'Hello, world!\n';
let s2 = "Success";
let s3 = `s1: ${s1}`;
void
型別用於指定函式沒有返回值。此型別只有一個值,同樣是void。由於void是引用型別,因此它可以用於泛型型別引數。
class A <T> {}
let instance: A <void>
Object
型別是所有引用型別的基型別。任何值,包括基本型別的值(它們會被自動裝箱),都可以直接被賦給Object型別的變數。
array
,即陣列。
enum
,列舉型別,是預先定義的一組命名值的值型別,其中命名值又稱為列舉常量。常量表示式可以用於顯式設定列舉常量的值。
union
,即聯合型別,是由多個型別組合成的引用型別。
type Animal = Cat | Dog | Frog | number;
let animal: Animal = new Cat();
animal = new Frog();
animal = 42;
if (animal instanceof Frog) {} // 判斷具體是哪種型別
運算子
===
:如果兩個運算元嚴格相等(型別也要相同),則返回true
==
:如果兩個運算元相等,則返回true
語句
if
語句:條件表示式可以是任何型別。但是對於boolean以外的型別,會進行隱式型別轉換
if ('Hello') {
console.log("Hello");
}
if (10086) {
console.log("Hello");
}
switch
語句:case、break、default
for
語句:使用for-of
語句可遍歷陣列或字串
for (let i = 0; i < 10; i += 2) {}
for (let ch of 'a string object') {}
break
語句可以終止迴圈語句或switch。break label
語句可以將控制流轉移到該識別符號所包含的語句塊之外。
異常處理:throw、try、catch、finally
throw new Error('this error')
函式
y 有預設值,z 為可選引數
function add(x: string, y: string = "-", z?: string): string {
return x + y + z
}
add("b") // "b-undefined"
add("b", "q") // "bqundefined"
add("b", "q", "t") // "bqt"
函式的最後一個引數可以是rest引數。
function sum(...numbers: number[]): number {}
sum();
sum(1);
sum(1, 2, 3);
函式型別
type XX = (x: number, y: number) => number // 函式型別
function do_action(f: XX) {
let result = f(2, 3); // 呼叫函式
console.log(result.toString())
}
do_action(Math.max); // 3
do_action(Math.min); // 2
do_action(Math.pow); // 8
箭頭函式,又名Lambda函式
閉包。閉包是由函式及宣告該函式的環境組合而成的。該環境包含了這個閉包建立時作用域內的任何區域性變數。
function f(): () => number {
let count = 0;
let g = (): number => {
count++;
console.log(count)
return count;
};
return g;
}
let z = f();
z(); // 返回:1
z(); // 返回:2
函式過載:為同一個函式寫入多個同名但簽名不同的函式頭,函式實現緊隨其後。
function foo(x: number): void; /* 第一個函式定義 */
function foo(x: string): void; /* 第二個函式定義 */
function foo(x: number | string): void {} /* 函式實現 */
foo(123); // OK,使用第一個定義
foo('aa'); // OK,使用第二個定義
類
可以使用關鍵字 new 建立例項,也可以使用物件字面量建立例項
關鍵字this
只能在類的例項方法、構造方法中使用。 不支援 this 型別
class Person {
name: string = ''; // 例項欄位,預設可見性為 public
private surname: string = ''; // 私有欄位
static numberX = 0; // 靜態欄位,靜態方法同理
constructor(n: string, sn: string) { // 建構函式
this.name = n;
this.surname = sn;
Person.numberX++;
}
fullName(): string { // 方法
return this.name + ' ' + this.surname;
}
}
let p1 = new Person("bat", "hh")
let p2 = {
n: "bqt",
sn: "hh"
}
ArkTS要求所有欄位在宣告時或者建構函式中顯式初始化。這和標準TS中的strictPropertyInitialization
模式一樣。
setter 和 getter 可用於提供對物件屬性的受控訪問。
屬性欄位只是 getter/setter對 的便捷寫法。
class Person {
private _age: number = 0;
get age(): number { return this._age; }
set age(x: number) {
this._age = x < 0 ? 0 : x;
}
}
let p1 = new Person()
p1.age = -1
console.log(p1.age)
繼承與實現:extends、implements、protected、super、override
建構函式過載,和普通的函式過載語法一樣
class C {
constructor(x: number) /* 第一個簽名 */
constructor(x: string) /* 第二個簽名 */
constructor(x: number | string) { /* 實現簽名 */
}
}
let c1 = new C(123); // OK,使用第一個簽名
let c2 = new C('abc'); // OK,使用第二個簽名
介面
介面屬性可以是欄位、getter、setter或getter和setter組合的形式。
介面也可以繼承其他介面。
interface X { }
interface Style extends X {
color: string // 屬性
siez: number
someMethod(): void // 方法,返回值型別即使是 void 也不能省略
}
class A implements Style {
color: string = ''; // 重寫屬性的第一種方式
get siez(): number { return 1 };// 重寫屬性的第二種方式
set siez(x: number) { };
someMethod() { }
}
泛型
泛型型別的型別引數可以設定預設值。在泛型函式呼叫中,型別實參可以顯式或隱式設定。
class Animal<T> { } // 泛型類和介面
let a = new Animal<string>();
class A { }
class B<K extends A, V = string> { name: K | undefined }
let b = new B<A, number>()
let c = new B<A>()
function last<T>(x: T[]): T {} // 泛型函式
last<number>([1, 2, 3]); // 顯式設定的型別實參
last([1, 2, 3]); // 隱式設定的型別實參
泛型Record<K, V>
用於將型別(鍵型別)的屬性對映到另一個型別(值型別)。常用物件字面量來初始化該型別的值。
型別K可以是字串型別或數值型別,而V可以是任何型別。
let map: Record<string, number> = {
'John': 25,
'Mary': 21,
}
map['John']; // 25
空安全
預設情況下,ArkTS中的所有型別都是不可為空
的,因此型別的值不能為空。這類似於TypeScript的嚴格空值檢查模式strictNullChecks
,但規則更嚴格。
let x: number = null; // 編譯時錯誤
let y: string = null; // 編譯時錯誤
let z: number[] = null; // 編譯時錯誤
可以為允許空值的變數定義為聯合型別 T | null
。
let x: number | null = null;
x = 1; // ok
x = null; // ok
if (x != null) {}
字尾運算子 !
可用於斷言其運算元為非空。
function foo(a: A | null) {
a.value; // 編譯時錯誤:無法訪問可空值的屬性
a!.value; // 編譯透過,如果執行時a的值為空,則發生執行時異常
}
空值合併二元運算子 ??
a ?? b
等價於三元運算子 (a != null && a != undefined) ? a : b
。
在訪問物件屬性時,如果該屬性是 undefined 或者 null,可選鏈運算子會返回 undefined。
// 返回型別必須為三者的聯合型別,因為該方法可能返回 null 或者 undefined
getNick(): string | null | undefined {
return this.spouse?.nick;
}
模組匯入匯出
程式可劃分為多組編譯單元或模組。
頂層語句是指在模組的最外層直接編寫的語句,這些語句不被包裹在任何函式、類、塊級作用域中。頂層語句包括變數宣告、函式宣告、表示式等。
每個模組都有其自己的作用域,即,在模組中建立的任何宣告(變數、函式、類等)在該模組之外都不可見,除非它們被顯式匯出。
匯出。可以使用關鍵字 export 匯出頂層的宣告。未匯出的宣告名稱被視為私有名稱,只能在宣告該名稱的模組中使用。
export class Point {}
export let Origin = new Point(0, 0);
export function show(): number {}
靜態匯入。匯入宣告用於匯入從其他模組匯出的實體,並在當前模組中提供其繫結。
import * as Utils from './utils' // 匯入繫結
Utils.X // 表示來自Utils的X
Utils.Y // 表示來自Utils的Y
import { X, Y } from './utils' // 將匯出的實體與指定名稱繫結
X // 表示來自utils的X
Y // 表示來自utils的Y
動態匯入:根據條件匯入模組或者按需匯入模組
import('modulePath') // 載入模組,並返回一個包含其所有匯出的模組物件
.then(obj => <module object>)
.catch(err => <loading error, e.g. if no such module>)
匯入 HarmonyOS SDK
HarmonyOS SDK 提供的開放能力也需要在匯入宣告後使用。
SDK 對同一個 Kit 下的介面模組進行了封裝,開發者在示例程式碼中可透過匯入 Kit 的方式來使用 Kit 所包含的介面能力。其中,Kit 封裝的介面模組可檢視 SDK 目錄下 Kit 子目錄中各 Kit 的定義。
透過匯入 Kit 方式使用開放能力有三種方式:
- 匯入單個模組的介面能力:
import { UIAbility } from '@kit.AbilityKit';
- 匯入多個模組的介面能力:
import { UIAbility, Ability, Context } from '@kit.AbilityKit';
- 匯入所有模組的介面能力:
import * as xxx from '@kit.AbilityKit';
方式三可能會匯入過多無需使用的模組,導致編譯後的 HAP 包太大,佔用過多資源,請謹慎使用。
2024.11.03