ArkTS-函數(shù)、模塊與關(guān)鍵字詳解

函數(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ì)象
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容