函数基础 #

一、函数概述 #

函数是可重用的代码块,用于执行特定任务。Deno/TypeScript支持多种函数定义方式,并提供强大的类型支持。

二、函数声明 #

2.1 基本语法 #

typescript
function functionName(parameters): returnType {
  // 函数体
  return value;
}

2.2 基本示例 #

typescript
function greet(name: string): string {
  return `Hello, ${name}!`;
}

console.log(greet("Deno")); // Hello, Deno!

2.3 无返回值 #

typescript
function log(message: string): void {
  console.log(message);
}

log("Hello"); // Hello

2.4 无参数 #

typescript
function getTimestamp(): number {
  return Date.now();
}

console.log(getTimestamp());

三、函数表达式 #

3.1 基本语法 #

typescript
const functionName = function(parameters): returnType {
  // 函数体
};

3.2 基本示例 #

typescript
const add = function(a: number, b: number): number {
  return a + b;
};

console.log(add(1, 2)); // 3

3.3 命名函数表达式 #

typescript
const factorial = function fact(n: number): number {
  if (n <= 1) return 1;
  return n * fact(n - 1);
};

console.log(factorial(5)); // 120

四、函数类型 #

4.1 定义函数类型 #

typescript
type MathOperation = (a: number, b: number) => number;

const add: MathOperation = (a, b) => a + b;
const subtract: MathOperation = (a, b) => a - b;
const multiply: MathOperation = (a, b) => a * b;

console.log(add(10, 5)); // 15
console.log(subtract(10, 5)); // 5
console.log(multiply(10, 5)); // 50

4.2 接口定义函数 #

typescript
interface StringProcessor {
  (input: string): string;
}

const toUpperCase: StringProcessor = (input) => input.toUpperCase();
const reverse: StringProcessor = (input) => input.split("").reverse().join("");

console.log(toUpperCase("hello")); // HELLO
console.log(reverse("hello")); // olleh

4.3 函数类型作为参数 #

typescript
function execute(
  a: number,
  b: number,
  operation: (x: number, y: number) => number
): number {
  return operation(a, b);
}

console.log(execute(10, 5, (x, y) => x + y)); // 15
console.log(execute(10, 5, (x, y) => x * y)); // 50

4.4 函数类型作为返回值 #

typescript
function createMultiplier(factor: number): (x: number) => number {
  return (x: number) => x * factor;
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

console.log(double(5)); // 10
console.log(triple(5)); // 15

五、函数重载 #

5.1 基本概念 #

函数重载允许同一函数名有多个签名:

typescript
function process(input: string): string;
function process(input: number): number;
function process(input: string | number): string | number {
  if (typeof input === "string") {
    return input.toUpperCase();
  }
  return input * 2;
}

console.log(process("hello")); // HELLO
console.log(process(5)); // 10

5.2 实际应用 #

typescript
interface User {
  id: number;
  name: string;
}

function getUser(id: number): User;
function getUser(name: string): User[];
function getUser(query: number | string): User | User[] {
  const users: User[] = [
    { id: 1, name: "Alice" },
    { id: 2, name: "Bob" },
    { id: 3, name: "Alice" }
  ];
  
  if (typeof query === "number") {
    return users.find(u => u.id === query) as User;
  }
  return users.filter(u => u.name === query);
}

console.log(getUser(1)); // { id: 1, name: "Alice" }
console.log(getUser("Alice")); // [{ id: 1, name: "Alice" }, { id: 3, name: "Alice" }]

六、立即执行函数(IIFE) #

6.1 基本语法 #

typescript
(function() {
  // 代码
})();

// 或
(() => {
  // 代码
})();

6.2 基本示例 #

typescript
const result = (function(a: number, b: number) {
  return a + b;
})(10, 5);

console.log(result); // 15

6.3 创建私有作用域 #

typescript
const counter = (() => {
  let count = 0;
  
  return {
    increment() { return ++count; },
    decrement() { return --count; },
    getCount() { return count; }
  };
})();

console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount()); // 2

七、递归函数 #

7.1 基本概念 #

函数调用自身:

typescript
function factorial(n: number): number {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}

console.log(factorial(5)); // 120

7.2 斐波那契数列 #

typescript
function fibonacci(n: number): number {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

console.log(fibonacci(10)); // 55

7.3 尾递归优化 #

typescript
function factorialTail(n: number, acc: number = 1): number {
  if (n <= 1) return acc;
  return factorialTail(n - 1, n * acc);
}

console.log(factorialTail(5)); // 120

八、回调函数 #

8.1 基本概念 #

函数作为参数传递:

typescript
function processArray(
  arr: number[],
  callback: (item: number, index: number) => number
): number[] {
  const result: number[] = [];
  for (let i = 0; i < arr.length; i++) {
    result.push(callback(arr[i], i));
  }
  return result;
}

const numbers = [1, 2, 3, 4, 5];

const doubled = processArray(numbers, (item) => item * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

const indexed = processArray(numbers, (item, index) => item + index);
console.log(indexed); // [1, 3, 5, 7, 9]

8.2 异步回调 #

typescript
function fetchData(
  url: string,
  callback: (error: Error | null, data?: string) => void
): void {
  setTimeout(() => {
    if (url.includes("error")) {
      callback(new Error("请求失败"));
    } else {
      callback(null, "数据内容");
    }
  }, 1000);
}

fetchData("https://api.example.com", (error, data) => {
  if (error) {
    console.error(error.message);
  } else {
    console.log(data);
  }
});

九、高阶函数 #

9.1 接受函数作为参数 #

typescript
function map<T, U>(
  arr: T[],
  transform: (item: T) => U
): U[] {
  const result: U[] = [];
  for (const item of arr) {
    result.push(transform(item));
  }
  return result;
}

const numbers = [1, 2, 3, 4, 5];
const strings = map(numbers, (n) => `Number: ${n}`);
console.log(strings); // ["Number: 1", "Number: 2", ...]

9.2 返回函数 #

typescript
function createLogger(prefix: string) {
  return function(message: string): void {
    console.log(`[${prefix}] ${message}`);
  };
}

const infoLogger = createLogger("INFO");
const errorLogger = createLogger("ERROR");

infoLogger("操作成功"); // [INFO] 操作成功
errorLogger("发生错误"); // [ERROR] 发生错误

9.3 函数组合 #

typescript
function compose<T>(...functions: Array<(arg: T) => T>): (arg: T) => T {
  return (arg: T) => functions.reduce((acc, fn) => fn(acc), arg);
}

const addOne = (x: number) => x + 1;
const double = (x: number) => x * 2;
const square = (x: number) => x * x;

const composed = compose(addOne, double, square);
console.log(composed(3)); // ((3 + 1) * 2)² = 64

十、函数属性 #

10.1 添加属性 #

typescript
function greet(name: string): string {
  return `Hello, ${name}!`;
}

greet.version = "1.0.0";
greet.author = "Deno";

console.log(greet("Alice")); // Hello, Alice!
console.log(greet.version); // 1.0.0

10.2 工厂函数 #

typescript
interface Counter {
  (): number;
  reset(): void;
  set(value: number): void;
}

function createCounter(): Counter {
  let count = 0;
  
  const counter = () => ++count;
  counter.reset = () => { count = 0; };
  counter.set = (value: number) => { count = value; };
  
  return counter;
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
counter.reset();
console.log(counter()); // 1

十一、最佳实践 #

11.1 单一职责 #

typescript
// 不推荐:函数做太多事
function processUser(user: { name: string; email: string }) {
  // 验证
  if (!user.name) throw new Error("名称必填");
  if (!user.email.includes("@")) throw new Error("邮箱无效");
  
  // 格式化
  user.name = user.name.trim();
  user.email = user.email.toLowerCase();
  
  // 保存
  console.log("保存用户...");
}

// 推荐:分离职责
function validateUser(user: { name: string; email: string }): void {
  if (!user.name) throw new Error("名称必填");
  if (!user.email.includes("@")) throw new Error("邮箱无效");
}

function formatUser(user: { name: string; email: string }): void {
  user.name = user.name.trim();
  user.email = user.email.toLowerCase();
}

function saveUser(user: { name: string; email: string }): void {
  console.log("保存用户...");
}

11.2 纯函数 #

typescript
// 不推荐:有副作用
let total = 0;
function addToTotal(value: number): number {
  total += value;
  return total;
}

// 推荐:纯函数
function sum(a: number, b: number): number {
  return a + b;
}

11.3 函数命名 #

typescript
// 不推荐:不清晰的命名
function process(data: unknown) { }
function handle(x: number, y: number) { }

// 推荐:清晰的命名
function validateEmail(email: string): boolean { }
function calculateTotal(price: number, quantity: number): number { }

十二、总结 #

本章学习了:

  • 函数声明和函数表达式
  • 函数类型定义
  • 函数重载
  • 立即执行函数(IIFE)
  • 递归函数
  • 回调函数
  • 高阶函数
  • 函数属性
  • 最佳实践

下一章,我们将学习箭头函数。

最后更新:2026-03-28