官方資料:
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/introduction-to-arkts-V5函數(shù)聲明
函數(shù)聲明引入一個(gè)函數(shù),包含其名稱、參數(shù)列表、返回類型和函數(shù)體。
以下示例是一個(gè)簡(jiǎn)單的函數(shù),包含兩個(gè)string類型的參數(shù),返回類型為string:
function add(x: string, y: string): string {
let z: string = `${x} ${y}`;
return z;
}
在函數(shù)聲明中,必須為每個(gè)參數(shù)標(biāo)記類型。如果參數(shù)為可選參數(shù),那么允許在調(diào)用函數(shù)時(shí)省略該參數(shù)。函數(shù)的最后一個(gè)參數(shù)可以是rest參數(shù)。
- 可選參數(shù)
可選參數(shù)的格式可為name?: Type。
function hello(name?: string) {
if (name == undefined) {
console.log('Hello!');
} else {
console.log(`Hello, ${name}!`);
}
}
可選參數(shù)的另一種形式為設(shè)置的參數(shù)默認(rèn)值。如果在函數(shù)調(diào)用中這個(gè)參數(shù)被省略了,則會(huì)使用此參數(shù)的默認(rèn)值作為實(shí)參。
function multiply(n: number, coeff: number = 2): number {
return n * coeff;
}
multiply(2); // 返回2*2
multiply(2, 3); // 返回2*3
- Rest參數(shù)
函數(shù)的最后一個(gè)參數(shù)可以是rest參數(shù)。使用rest參數(shù)時(shí),允許函數(shù)或方法接受任意數(shù)量的實(shí)參。
function sum(...numbers: number[]): number {
let res = 0;
for (let n of numbers)
res += n;
return res;
}
sum() // 返回0
sum(1, 2, 3) // 返回6
- 返回類型
如果可以從函數(shù)體內(nèi)推斷出函數(shù)返回類型,則可在函數(shù)聲明中省略標(biāo)注返回類型。
// 顯式指定返回類型
function foo(): string { return 'foo'; }
// 推斷返回類型為string
function goo() { return 'goo'; }
不需要返回值的函數(shù)的返回類型可以顯式指定為void或省略標(biāo)注。這類函數(shù)不需要返回語(yǔ)句。
以下示例中兩種函數(shù)聲明方式都是有效的:
function hi1() { console.log('hi'); }
function hi2(): void { console.log('hi'); }
- 函數(shù)的作用域
函數(shù)中定義的變量和其他實(shí)例僅可以在函數(shù)內(nèi)部訪問(wèn),不能從外部訪問(wèn)。
如果函數(shù)中定義的變量與外部作用域中已有實(shí)例同名,則函數(shù)內(nèi)的局部變量定義將覆蓋外部定義。
- 函數(shù)調(diào)用
函數(shù)類型通常用于定義回調(diào):
type trigFunc = (x: number) => number // 這是一個(gè)函數(shù)類型
function do_action(f: trigFunc) {
f(3.141592653589); // 調(diào)用函數(shù)
}
do_action(Math.sin); // 將函數(shù)作為參數(shù)傳入
- 箭頭函數(shù)(又名Lambda函數(shù))
函數(shù)可以定義為箭頭函數(shù),例如:
let sum = (x: number, y: number): number => {
return x + y;
}
箭頭函數(shù)的返回類型可以省略;省略時(shí),返回類型通過(guò)函數(shù)體推斷。
表達(dá)式可以指定為箭頭函數(shù),使表達(dá)更簡(jiǎn)短,因此以下兩種表達(dá)方式是等價(jià)的:
let sum1 = (x: number, y: number) => { return x + y; }
let sum2 = (x: number, y: number) => x + y
- 閉包
閉包是由函數(shù)及聲明該函數(shù)的環(huán)境組合而成的。該環(huán)境包含了這個(gè)閉包創(chuàng)建時(shí)作用域內(nèi)的任何局部變量。
在下例中,f函數(shù)返回了一個(gè)閉包,它捕獲了count變量,每次調(diào)用z,count的值會(huì)被保留并遞增。
function f(): () => number {
let count = 0;
let g = (): number => { count++; return count; };
return g;
}
let z = f();
z(); // 返回:1
z(); // 返回:2
- 函數(shù)重載
我們可以通過(guò)編寫重載,指定函數(shù)的不同調(diào)用方式。具體方法為,為同一個(gè)函數(shù)寫入多個(gè)同名但簽名不同的函數(shù)頭,函數(shù)實(shí)現(xiàn)緊隨其后。
function foo(x: number): void; /* 第一個(gè)函數(shù)定義 */
function foo(x: string): void; /* 第二個(gè)函數(shù)定義 */
function foo(x: number | string): void { /* 函數(shù)實(shí)現(xiàn) */
}
foo(123); // OK,使用第一個(gè)定義
foo('aa'); // OK,使用第二個(gè)定義
不允許重載函數(shù)有相同的名字以及參數(shù)列表,否則將會(huì)編譯報(bào)錯(cuò)。
模塊
程序可劃分為多組編譯單元或模塊。
每個(gè)模塊都有其自己的作用域,即,在模塊中創(chuàng)建的任何聲明(變量、函數(shù)、類等)在該模塊之外都不可見(jiàn),除非它們被顯式導(dǎo)出。
與此相對(duì),從另一個(gè)模塊導(dǎo)出的變量、函數(shù)、類、接口等必須首先導(dǎo)入到模塊中。
導(dǎo)出
可以使用關(guān)鍵字export導(dǎo)出頂層的聲明。
未導(dǎo)出的聲明名稱被視為私有名稱,只能在聲明該名稱的模塊中使用。
注意:通過(guò)export方式導(dǎo)出,在導(dǎo)入時(shí)要加{}。
export class Point {
x: number = 0
y: number = 0
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
export let Origin = new Point(0, 0);
export function Distance(p1: Point, p2: Point): number {
return Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
}
導(dǎo)入
- 靜態(tài)導(dǎo)入
導(dǎo)入聲明用于導(dǎo)入從其他模塊導(dǎo)出的實(shí)體,并在當(dāng)前模塊中提供其綁定。導(dǎo)入聲明由兩部分組成:
導(dǎo)入路徑,用于指定導(dǎo)入的模塊;
導(dǎo)入綁定,用于定義導(dǎo)入的模塊中的可用實(shí)體集和使用形式(限定或不限定使用)。
導(dǎo)入綁定可以有幾種形式。
假設(shè)模塊具有路徑“./utils”和導(dǎo)出實(shí)體“X”和“Y”。
導(dǎo)入綁定* as A表示綁定名稱“A”,通過(guò)A.name可訪問(wèn)從導(dǎo)入路徑指定的模塊導(dǎo)出的所有實(shí)體:
import * as Utils from './utils'
Utils.X // 表示來(lái)自Utils的X
Utils.Y // 表示來(lái)自Utils的Y
導(dǎo)入綁定{ ident1, ..., identN }表示將導(dǎo)出的實(shí)體與指定名稱綁定,該名稱可以用作簡(jiǎn)單名稱:
import { X, Y } from './utils'
X // 表示來(lái)自u(píng)tils的X
Y // 表示來(lái)自u(píng)tils的Y
如果標(biāo)識(shí)符列表定義了ident as alias,則實(shí)體ident將綁定在名稱alias下:
import { X as Z, Y } from './utils'
Z // 表示來(lái)自Utils的X
Y // 表示來(lái)自Utils的Y
X // 編譯時(shí)錯(cuò)誤:'X'不可見(jiàn)
- 動(dòng)態(tài)導(dǎo)入
應(yīng)用開發(fā)的有些場(chǎng)景中,如果希望根據(jù)條件導(dǎo)入模塊或者按需導(dǎo)入模塊,可以使用動(dòng)態(tài)導(dǎo)入代替靜態(tài)導(dǎo)入。
import()語(yǔ)法通常稱為動(dòng)態(tài)導(dǎo)入dynamic import,是一種類似函數(shù)的表達(dá)式,用來(lái)動(dòng)態(tài)導(dǎo)入模塊。以這種方式調(diào)用,將返回一個(gè)promise。
如下例所示,import(modulePath)可以加載模塊并返回一個(gè)promise,該promise resolve為一個(gè)包含其所有導(dǎo)出的模塊對(duì)象。該表達(dá)式可以在代碼中的任意位置調(diào)用。
let modulePath = prompt("Which module to load?");
import(modulePath)
.then(obj => <module object>)
.catch(err => <loading error, e.g. if no such module>)
如果在異步函數(shù)中,可以使用let module = await import(modulePath)。
// say.ts
export function hi() {
console.log('Hello');
}
export function bye() {
console.log('Bye');
}
那么,可以像下面這樣進(jìn)行動(dòng)態(tài)導(dǎo)入:
async function test() {
let ns = await import('./say');
let hi = ns.hi;
let bye = ns.bye;
hi();
bye();
}
關(guān)鍵字
this
關(guān)鍵字this只能在類的實(shí)例方法中使用。
class A {
count: string = 'a'
m(i: string): void {
this.count = i;
}
}
使用限制:
- 不支持this類型
- 不支持在函數(shù)和類的靜態(tài)方法中使用this
class A {
n: number = 0
f1(arg1: this) {} // 編譯時(shí)錯(cuò)誤,不支持this類型
static f2(arg1: number) {
this.n = arg1; // 編譯時(shí)錯(cuò)誤,不支持在類的靜態(tài)方法中使用this
}
}
function foo(arg1: number) {
this.n = i; // 編譯時(shí)錯(cuò)誤,不支持在函數(shù)中使用this
}
關(guān)鍵字this的指向:
- 調(diào)用實(shí)例方法的對(duì)象
- 正在構(gòu)造的對(duì)象