面试题答案
一键面试以下是用 Rust 语言实现的示例代码及解释:
// 定义泛型函数,接受泛型参数 T
fn create_closure<T>(param: T)
where
// 这里添加类型约束,例如 T 必须实现 Copy 特征,以便在闭包中使用
T: Copy + std::ops::Add<Output = T>,
{
// 返回一个闭包
let closure = move || {
// 闭包利用传入的泛型参数进行特定操作,这里是加法计算
param + param
};
// 调用闭包并打印结果
println!("Result: {:?}", closure());
}
类型约束
where
子句:在函数定义后使用where
关键字,指定泛型T
必须实现Copy
和Add
特征。Copy
特征允许我们在闭包中使用参数param
,因为闭包捕获变量默认会转移所有权,而实现Copy
特征则可以避免所有权转移。Add
特征是为了实现我们对泛型类型数据进行加法计算的操作。
生命周期
move
关键字:在闭包定义前使用move
关键字,确保闭包获取param
的所有权,而不是引用。这在函数返回闭包时非常重要,因为闭包可能在函数结束后继续存在。如果不使用move
,闭包可能会引用函数栈上的局部变量,当函数返回后该变量被销毁,导致悬垂引用。
在其他编程语言中,如 TypeScript,虽然没有像 Rust 那样严格的生命周期概念,但也有类型约束:
// 定义泛型函数,接受泛型参数 T
function createClosure<T extends number | string>(param: T): () => T {
// 返回一个闭包
return () => {
// 这里针对 number 和 string 类型分别进行特定操作
if (typeof param === 'number') {
return param + param;
} else {
return param + param;
}
};
}
// 使用示例
const numClosure = createClosure(5);
console.log(numClosure());
const strClosure = createClosure('hello ');
console.log(strClosure());
类型约束
extends
关键字:在泛型参数T
后使用extends
关键字,指定T
必须是number
或string
类型,这就限制了传入的泛型类型,确保闭包内的操作是类型安全的。
在 JavaScript 中(没有严格的类型约束,但可使用 JSDoc 进行类型提示):
/**
* 创建闭包函数
* @template T 泛型参数,可传入 number 或 string
* @param {T} param 泛型参数
* @returns {() => T} 返回一个闭包
*/
function createClosure(param) {
return () => {
if (typeof param === 'number') {
return param + param;
} else if (typeof param ==='string') {
return param + param;
}
};
}
// 使用示例
const numClosure = createClosure(5);
console.log(numClosure());
const strClosure = createClosure('hello ');
console.log(strClosure());
这里通过 JSDoc 进行类型提示,在实际运行时仍需要开发者确保传入参数的类型正确性,以保证闭包内操作的有效性。