当前位置: 首页 > news >正文

Typescript学习教程,从入门到精通,TypeScript 函数语法知识点及案例代码(5)

TypeScript 函数语法知识点及案例代码

TypeScript 提供了丰富的函数语法特性,使得函数定义更加灵活和强大。以下将详细介绍 TypeScript 中函数的相关语法,包括函数定义、可选参数、默认参数、剩余参数、重载函数、递归函数、匿名函数、箭头函数以及回调函数。

函数定义

在 TypeScript 中,函数可以通过 function 关键字来定义,也可以使用箭头函数(=>)。

// 基本函数定义
function greet(name: string): string {return `Hello, ${name}!`;
}// 函数表达式
const greet2 = function(name: string): string {return `Hello, ${name}!`;
};// 调用函数
console.log(greet("Alice")); // 输出: Hello, Alice!
console.log(greet2("Bob"));  // 输出: Hello, Bob!// 无返回值函数
function logMessage(message: string): void {console.log(message);
}// 函数类型
type GreetFunction = (name: string) => string;
const greet3: GreetFunction = function(name) {return `Hello, ${name}!`;
};

可选参数、默认参数和剩余参数

可选参数

// 可选参数使用?标记
function buildName(firstName: string, lastName?: string): string {if (lastName) {return `${firstName} ${lastName}`;} else {return firstName;}
}console.log(buildName("Alice"));       // 输出: Alice
console.log(buildName("Alice", "Smith")); // 输出: Alice Smith

默认参数

// 默认参数
function buildName2(firstName: string, lastName: string = "Doe"): string {return `${firstName} ${lastName}`;
}console.log(buildName2("John"));       // 输出: John Doe
console.log(buildName2("John", "Smith")); // 输出: John Smith

剩余参数

// 剩余参数(可变参数)
function sum(...numbers: number[]): number {return numbers.reduce((total, num) => total + num, 0);
}console.log(sum(1, 2, 3));       // 输出: 6
console.log(sum(1, 2, 3, 4, 5)); // 输出: 15// 剩余参数也可以和其他参数一起使用
function greetPeople(greeting: string, ...names: string[]): string {return `${greeting} ${names.join(", ")}!`;
}console.log(greetPeople("Hello", "Alice", "Bob", "Charlie")); 
// 输出: Hello Alice, Bob, Charlie!

重载函数

函数重载允许一个函数接受不同数量或类型的参数时,做出不同的处理。

// 函数重载
function makeDate(timestamp: number): Date;
function makeDate(year: number, month: number, day: number): Date;
function makeDate(yearOrTimestamp: number, month?: number, day?: number): Date {if (month !== undefined && day !== undefined) {return new Date(yearOrTimestamp, month - 1, day);} else {return new Date(yearOrTimestamp);}
}const d1 = makeDate(1234567890000); // 使用时间戳
const d2 = makeDate(2023, 5, 17);   // 使用年月日console.log(d1); // 输出: 2009-02-13T23:31:30.000Z
console.log(d2); // 输出: 2023-05-16T16:00:00.000Z (注意月份是0-based)// 另一个重载例子
function reverse(value: string): string;
function reverse<T>(value: T[]): T[];
function reverse(value: string | any[]): string | any[] {if (typeof value === "string") {return value.split("").reverse().join("");} else {return value.slice().reverse();}
}console.log(reverse("hello"));      // 输出: olleh
console.log(reverse([1, 2, 3]));    // 输出: [3, 2, 1]

递归函数

递归函数是调用自身的函数,常用于解决分治问题。

// 阶乘函数
function factorial(n: number): number {if (n <= 1) return 1;return n * factorial(n - 1);
}console.log(factorial(5)); // 输出: 120// 斐波那契数列
function fibonacci(n: number): number {if (n <= 1) return n;return fibonacci(n - 1) + fibonacci(n - 2);
}console.log(fibonacci(10)); // 输出: 55// 尾递归优化版本(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

匿名函数

匿名函数是没有名称的函数,通常作为参数传递或立即执行。

// 作为参数传递
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(function(num) {return num * 2;
});
console.log(doubled); // 输出: [2, 4, 6, 8, 10]// 立即调用的函数表达式(IIFE)
(function() {console.log("This runs immediately");
})();// 带有类型的匿名函数
const greetAnonymous: (name: string) => string = function(name) {return `Hello, ${name}!`;
};
console.log(greetAnonymous("Dave")); // 输出: Hello, Dave!

箭头函数

箭头函数是ES6引入的简洁函数语法,自动绑定this。

// 基本箭头函数
const greetArrow = (name: string): string => `Hello, ${name}!`;
console.log(greetArrow("Eve")); // 输出: Hello, Eve!// 多行箭头函数
const sumArrow = (a: number, b: number): number => {const result = a + b;return result;
};
console.log(sumArrow(3, 4)); // 输出: 7// this绑定示例
class Counter {count = 0;increment() {setTimeout(function() {// 这里的this指向window/undefined,因为普通函数有自己的this// this.count++; // 会报错}, 1000);setTimeout(() => {// 箭头函数不绑定自己的this,所以这里的this指向Counter实例this.count++;console.log(this.count); // 1秒后输出: 1}, 1000);}
}const counter = new Counter();
counter.increment();// 箭头函数作为回调
const numbers = [1, 2, 3];
const squares = numbers.map(n => n * n);
console.log(squares); // 输出: [1, 4, 9]

回调函数

回调函数是作为参数传递给另一个函数的函数,在特定事件或条件发生时被调用。

// 基本回调函数
function fetchData(callback: (data: string) => void) {// 模拟异步操作setTimeout(() => {callback("Data received");}, 1000);
}fetchData((data) => {console.log(data); // 1秒后输出: Data received
});// 错误优先回调(Node.js风格)
function readFile(callback: (error: Error | null, data?: string) => void) {const success = Math.random() > 0.5;setTimeout(() => {if (success) {callback(null, "File content");} else {callback(new Error("Failed to read file"));}}, 1000);
}readFile((err, data) => {if (err) {console.error("Error:", err.message);} else {console.log("Data:", data);}
});// 使用接口定义回调类型
interface Callback<T> {(err: Error | null, result?: T): void;
}const dbQuery: Callback<string> = function(cb) {setTimeout(() => {cb(null, "Query results");}, 500);
};dbQuery((err, result) => {if (err) {console.error(err);} else {console.log(result); // 输出: Query results}
});

实战闯关——基础语法

闯关1:实现一个计算器函数

/*** 实现一个计算器函数* @param operator 运算符,可以是 '+', '-', '*', '/'* @param operands 操作数数组* @returns 计算结果*/
function calculate(operator: '+' | '-' | '*' | '/', ...operands: number[]): number {if (operands.length === 0) return 0;switch (operator) {case '+':return operands.reduce((sum, num) => sum + num, 0);case '-':return operands.slice(1).reduce((diff, num) => diff - num, operands[0]);case '*':return operands.reduce((product, num) => product * num, 1);case '/':return operands.slice(1).reduce((quotient, num) => quotient / num, operands[0]);default:throw new Error(`Unknown operator: ${operator}`);}
}console.log(calculate('+', 1, 2, 3));   // 输出: 6
console.log(calculate('-', 10, 2, 3));  // 输出: 5
console.log(calculate('*', 2, 3, 4));   // 输出: 24
console.log(calculate('/', 20, 2, 5));  // 输出: 2

闯关2:实现一个柯里化函数

/*** 柯里化函数* @param fn 要柯里化的函数* @returns 柯里化后的函数*/
function curry<T, R>(fn: (...args: T[]) => R): (...args: T[]) => R | ((...args: T[]) => R) {return function curried(...args: T[]): R | ((...args: T[]) => R) {if (args.length >= fn.length) {return fn(...args);} else {return (...moreArgs: T[]) => curried(...args, ...moreArgs);}};
}// 测试柯里化
function add(a: number, b: number, c: number): number {return a + b + c;
}const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3));     // 输出: 6
console.log(curriedAdd(1, 2)(3));    // 输出: 6
console.log(curriedAdd(1)(2, 3));    // 输出: 6
console.log(curriedAdd(1, 2, 3));    // 输出: 6

闯关3:实现一个记忆化函数

/*** 记忆化函数,缓存函数结果* @param fn 需要记忆化的函数* @returns 记忆化后的函数*/
function memoize<T extends (...args: any[]) => any>(fn: T): T {const cache = new Map<string, ReturnType<T>>();return function(...args: Parameters<T>): ReturnType<T> {const key = JSON.stringify(args);if (cache.has(key)) {return cache.get(key)!;}const result = fn(...args);cache.set(key, result);return result;} as T;
}// 测试记忆化
function expensiveCalculation(n: number): number {console.log(`Calculating for ${n}...`);return n * n;
}const memoizedCalculation = memoize(expensiveCalculation);
console.log(memoizedCalculation(5)); // 输出: Calculating for 5... 然后 25
console.log(memoizedCalculation(5)); // 直接输出: 25 (没有计算)
console.log(memoizedCalculation(3)); // 输出: Calculating for 3... 然后 9
console.log(memoizedCalculation(3)); // 直接输出: 9 (没有计算)

闯关4:实现一个管道函数

/*** 管道函数,将多个函数组合成一个从左到右执行的函数链* @param functions 要组合的函数数组* @returns 组合后的函数*/
function pipe<T>(...functions: Array<(arg: T) => T>): (arg: T) => T {return (input: T) => functions.reduce((acc, fn) => fn(acc), input);
}// 测试管道函数
function add5(x: number): number {return x + 5;
}function multiply3(x: number): number {return x * 3;
}function subtract10(x: number): number {return x - 10;
}const transform = pipe(add5, multiply3, subtract10);
console.log(transform(10)); // 计算过程: (10 + 5) = 15 → (15 * 3) = 45 → (45 - 10) = 35

闯关5:实现一个防抖函数

/*** 防抖函数,在延迟时间内只执行最后一次调用* @param fn 要防抖的函数* @param delay 延迟时间(毫秒)* @returns 防抖后的函数*/
function debounce<T extends (...args: any[]) => any>(fn: T, delay: number): (...args: Parameters<T>) => void {let timeoutId: ReturnType<typeof setTimeout>;return function(...args: Parameters<T>): void {clearTimeout(timeoutId);timeoutId = setTimeout(() => {fn(...args);}, delay);};
}// 测试防抖函数
function search(query: string): void {console.log(`Searching for: ${query}`);
}const debouncedSearch = debounce(search, 500);// 快速连续调用
debouncedSearch("a");
debouncedSearch("ab");
debouncedSearch("abc");// 500毫秒后只会输出: Searching for: abc

这些示例涵盖了TypeScript函数的主要概念和实际应用场景,从基础到高级功能都有涉及。

相关文章:

  • 六、绘制图片
  • Golang 范型
  • C# WPF .NET Core和.NET5之后引用System.Windows.Forms的解决方案
  • 数据库——SQL约束窗口函数介绍
  • 量化用到的机器学习书籍推荐
  • 广和通L610模块通过AT指令访问服务器方案:嵌赛使用
  • QT6 源(105)篇二:阅读与注释 QAction,给出源代码
  • RJ连接器的未来:它还会是网络连接的主流标准吗?
  • Java-Objects类高效应用的全面指南
  • Vue百日学习计划Day19-20天详细计划-Gemini版
  • 从数据分析到数据可视化:揭开数据背后的故事
  • ArrayList-集合使用
  • 【C语言练习】046. 编写插入排序算法
  • 编译原理实验五:LR语法分析器的控制程序
  • BrepGen中的几何特征组装与文件保存详解 deepwiki occwl OCC包装库
  • 亲测有效!OGG 创建抽取进程报错 OGG-08241,如何解决?
  • gRPC开发指南:Visual Studio 2022 + Vcpkg + Windows全流程配置
  • 深入理解 Java 字节码操作码
  • Rust 数据结构:HashMap
  • 【沉浸式求职学习day42】【算法题:滑动窗口】
  • 美国失去最后一个AAA评级,资产价格怎么走?美股或将触及天花板
  • 尹锡悦宣布退出国民力量党
  • 俄乌直接谈判结束,乌称“毫无成果”
  • 刘国中将出席第78届世界卫生大会并顺访瑞士、访问白俄罗斯
  • 新版城市规划体检评估解读:把城市安全韧性摆在更加突出位置
  • 日本一季度实际GDP环比下降0.2%