引言
众所周知, JS 默认是不支持函数重载的, 如果强制这么写会出现下面这种情况:
1 2 3 4 5 6 7 8 9 10
| const search = (name) => { console.log("按照名字查找"); };
const search = (name, age) => { console.log("按照名字和年龄查找"); };
search("Kaede"); search("YYT", 18);
|
1 2 3
| const search = (name, age) => { ^ SyntaxError: Identifier 'search' has already been declared
|
所以应该怎么实现函数的重载呢? 这里有两种方案.
方案 1
我们可以创建一个类, 然后给这个类添加多个同名函数, 进而实现重载. 这是 JQuery 中的做法. 不过这里的添加函数的方法需要单独实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| function addMethod(Object, name, fn) { const old = Object[name]; Object[name] = function (...args) { if (args.length === fn.length) { return fn.apply(this, args); } else if (typeof old === "function") { return old.apply(this, args); } }; }
const tool = {};
addMethod(tool, "search", () => { console.log("直接查找用户"); });
addMethod(tool, "search", (name) => { console.log("通过姓名查找用户"); });
addMethod(tool, "search", (name, age) => { console.log("通过姓名和年龄查找用户"); });
tool.search(); tool.search("Kaede"); tool.search("Yyt", 18);
|
则输出正常. 重载成功.
1 2 3
| 直接查找用户 通过姓名查找用户 通过姓名和年龄查找用户
|
问题就是不方便, 它是一个对象; 另外这里只能判断参数的数量, 不能判断参数的类型, 不是很好.
方案 2
通过一个映射来实现即可. 还是写一个工具函数出来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| const createOverload = () => { const fnMap = new Map();
const overload = (...args) => { const key = args.map((item) => typeof item).join(".");
const fn = fnMap.get(key);
if (!fn) { throw new TypeError("没有找到对应的实现"); }
return fn.apply(this, args); };
overload.addImpl = (...args) => { const fn = args.pop(); if (typeof fn !== "function") { throw new TypeError("最后一个参数应当为函数"); } const key = args.join("."); fnMap.set(key, fn); };
return overload; };
|
随后, 按照如下方式进行调用即可.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import { createOverload } from "./util.js"; const getData = createOverload();
getData.addImpl(() => { console.log("空参的函数"); });
getData.addImpl("string", (name) => { console.log("根据姓名查找 姓名为" + name); });
getData.addImpl("string", "number", (name, age) => { console.log("根据姓名和年龄查找 分别为:" + name + ", " + age); });
getData(); getData("Kaede"); getData("YYT", 18); getData("YYT", "LC");
|
输出如下, 可以看到能够根据类型正确的重载函数了.
1 2 3 4 5 6 7 8
| 空参的函数 根据姓名查找 姓名为Kaede 根据姓名和年龄查找 分别为:YYT, 18 file:///D:/Documents/WorkSpace/test-projects/js-temp/util.js:15 throw new TypeError("没有找到对应的实现"); ^
TypeError: 没有找到对应的实现
|