Harmony NEXT开发进阶:函数声明、闭包与重载的深度指南

函数

函数的声明

什么是函数?

函数声明引入一个函数,包含其名称、参数列表、返回类型和函数体。

在函数声明中,必须为每个参数标记类型。如果参数为可选参数,那么允许在调用函数时省略该参数。函数的最后一个参数可以是rest参数。

以下示例是一个简单的函数,包含两个string类型的参数,返回类型为string:

function add(x: string, y: string): string {
  let z: string = `${x} ${y}`;
  return z;
}

Rest参数

函数的最后一个参数可以是rest参数。使用rest参数时,允许函数或方法接受任意数量的实参。

function sum(...numbers: number[]): number {
  let res = 0;
  for (let n of numbers)
    res += n;
  return res;
}

sum() // 返回0
sum(1, 2, 3) // 返回6

可选参数

可选参数的格式可为name?: Type。

function hello(name?: string) {
  if (name == undefined) {
    console.log('Hello!');
  } else {
    console.log(`Hello, ${name}!`);
  }
}

function multiply(n: number, coeff: number = 2): number {
  return n * coeff;
}
multiply(2);  // 返回2*2
multiply(2, 3); // 返回2*3

返回类型

如果可以从函数体内推断出函数返回类型,则可在函数声明中省略标注返回类型

// 显式指定返回类型
function foo(): string { return 'foo'; }

// 推断返回类型为string
function goo() { return 'goo'; }

不需要返回值使用void或者隐式不标注

函数的作用域

函数中定义的变量和其他实例仅可以在函数内部访问,不能从外部访问。

如果函数中定义的变量与外部作用域中已有实例同名,则函数内的局部变量定义将覆盖外部定义。

函数类型

函数类型通常用于定义回调:

type trigFunc = (x: number) => number // 这是一个函数类型

function do_action(f: trigFunc) {
   f(3.141592653589); // 调用函数
}

do_action(Math.sin); // 将函数作为参数传入

常规函数

/**
 * 函数:使用关键字function定义,可以被重复调用的代码块
 * 目的:为了解决代码冗余,使得代码更加简洁,提升代码效率
 * 结构:
 * 1、无参
 *  function 函数名():返回值类型{
 *  函数体
 * //return 结果
 * }
 * 调用:函数名()
 * 2、有参
 * function 函数名(形参:类型):返回值类型{
 * 函数体
 * //return 结果
 * }
 * 调用:函数名()
 *
 * 返回值:
 *  可以显性/隐性,根据return推断
 */

function say() {
  console.info("hello")
}

say()

function sum(ageA: number, ageB: number): number {
  return ageA + ageB
}

let sumAge = sum(18, 20)
console.info("sumAge:", sumAge)

箭头函数

/**
 * 箭头函数/Lambda函数:
 *  结构: let 函数名 = (形参1:类型,形参2:类型2...): 返回值类型 => {
 *  函数逻辑
 *  return 返回值
 * }
 * 
 * 或者 let 函数名 = (形参1:类型,形参2:类型2...) => 返回值 
 * 
 * 调用:函数名(实参...)
 *
 */
let say = (): void => {
  console.info("hello")
}
say()

//自己修改上面函数第二个sum方法,改为箭头函数的形式

函数的调用

调用函数以执行其函数体,实参值会赋值给函数的形参。

function join(x: string, y: string): string {
  let z: string = `${x} ${y}`;
  return z;
}
let x = join('hello', 'world');
console.log(x);

闭包

闭包是由函数及声明该函数的环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。

在下例中,f函数返回了一个闭包,它捕获了count变量,每次调用z,count的值会被保留并递增。

function f(): () => number {
  let count = 0;
  let g = (): number => {
    count++;
    return count;
  };
  return g;
}

let z = f();
console.info("z1:", z())
console.info("z2:", z())

函数重载

我们可以通过编写重载,指定函数的不同调用方式。具体方法为,为同一个函数写入多个同名但签名不同的函数头,函数实现紧随其后

不允许重载函数有相同的名字以及参数列表,否则将会编译报错。

function foo(x: number): void;            /* 第一个函数定义 */
function foo(x: string): void;            /* 第二个函数定义 */
function foo(x: number | string): void {  /* 函数实现 */
}

foo(123);     //  OK,使用第一个定义
foo('aa'); // OK,使用第二个定义
posted @ 2025-02-28 19:02  鸿蒙布道师  阅读(84)  评论(0)    收藏  举报  来源