概述
众所周知,js里面是没有函数重载这一说的,主要有如下的几个原因:
1. 动态类型语言特性
JavaScript 是一种动态类型语言,函数的参数在定义时不需要指定类型。这与支持重载的静态类型语言(如 Java、C++)不同,那些语言可以根据参数类型和数量来区分不同的函数实现。
2. 函数参数处理机制
JavaScript 函数在被调用时:
- 不检查参数数量(可以传递比声明多或少的所有参数)
- 所有参数都被存储在
arguments
对象中(ES6 之前) - 多余的参数会被忽略,缺少的参数会被赋值为
undefined
3. 函数签名唯一性
在 JavaScript 中,函数名是唯一的标识符,后定义的函数会覆盖同名的先前定义,无法像传统重载那样保留多个版本。
模拟实现
核心思路:闭包,通过借助闭包函数的缓存特性,返回加工后的函数,然后通过map缓存对于参数类型到函数具体实现,即可实现重载
实现
js
// 构造重载函数
function createOverload() {
// 定义一个map结构,缓存不同参数类型对应的函数实现
const fnMap = new Map();
function overload(...args) {
// 获取调用参数的类型列表
const key = args.map((arg) => typeof arg).join(",");
// 从map中获取对应的函数实现
const fn = fnMap.get(key);
if (!fn) {
throw new Error(`No function registered for arguments: ${key}`);
}
// 调用对应的函数实现
return fn.apply(this, args);
}
// 追加重载实现函数
overload.addImpl = function (...args) {
console.log("Adding implementation for:", args);
// 最后一个参数必须是函数
const fn = args.pop();
if (typeof fn !== "function") {
throw new Error("Last argument must be a function");
}
console.log("fn-map", fnMap);
const key = args.join(",");
// 将参数类型作为key存储函数实现
fnMap.set(key, fn);
};
return overload;
}
const getUsers = createOverload();
// 无参情况
getUsers.addImpl(() => {
console.log("No arguments provided");
});
const searchPage = (page, size = 10) => {
console.log(`Searching page ${page} with size ${size}`);
};
// 参数:number
getUsers.addImpl("number", searchPage);
// 参数:number, number
getUsers.addImpl("number", "number", searchPage);
// 参数:string
getUsers.addImpl("string", (name) => {
console.log("String argument provided", name);
});
// 参数:string:number
getUsers.addImpl("string", "number", (name, age) => {
console.log(`Searching for user ${name} with age ${age}`);
});
// 使用
getUsers();
getUsers(1); // Searching page 1 with size 10
getUsers(1, 20); // Searching page 1 with size 20
getUsers("Alice"); // String argument provided
getUsers("Alice", 30); // Searching for user Alice with age 30
结果

总结
虽然js中并不存在函数重载,但是我们依然能够通过间接形式实现对于的功能。