Js模拟函数重载小白知识
背景
《JavaScript高级程序设计》中提及,JavaScript 不支持函数重载。若出现函数名称相同情况下,后者覆盖前者,故此不会出现重载的情况。
函数重载
函数重载(英语:function overloading),是Ada、C++、C#、D和Java等编程语言中具有的一项特性,这项特性允许创建数项名称相同但输入输出类型或个数不同的子程序,它可以简单地称为一个单独功能可以执行多项任务的能力。
场景
例如,一个工厂有着数量级的员工,期望通过姓名找到某一员工或某类员工,使用同一个方法通过透传参数个数去查找员工。
一般实现:
var people = {arguments 和 switch
names: ["张一", "张二", "张三", "张四", "李一", "李二", "李三", "李四"]
};
// 找全员工
function find() {
return people.names;
}
// 全量员工中,找到名字中带有特殊”字“的员工
function find1(name) {
return people.names.filter(item => item.includes(name));
}
// 全量员工中,找到名字中带有多个特殊"字"的员工
function find2(name1, name2) {
return people.names.filter(item => item.includes(name1) && item.includes(name2));
}
find(); // ["张一", "张二", "张三", "张四", "李一", "李二", "李三", "李四"]
find1('张'); // ["张一", "张二", "张三"]
find2('李', '四') // ['李四']
函数重载,第一种方式:使用 arguments + switch
var people = {
names: ["张一", "张二", "张三", "张四", "李一", "李二", "李三", "李四"]
};
// arguments + switch方式
people.find() {
switch(arguments.length) {
case: 0
return this.names;
case: 1
return this.names.filter(item => item.includes(arguments[0]));
case: 2
return this.names.filter(item => item.includes(arguments[1]) && item.includes(arguments[2]));
}
}
people.find(); // ["张一", "张二", "张三", "张四", "李一", "李二", "李三", "李四"]
people.find('张'); // ["张一", "张二", "张三"]
people.find('李', '四') // ['李四']
函数重载,第二种方式:使用 arguments + 闭包
item.includes(name));
}
// 全量员工中,找到名字中带有多个特殊"字"的员工
function find2(name1, name2) {
return this.names.filter(item => item.includes(name1) && item.includes(name2));
}
// 全量员工的前 count 名
function find3(count) {
return this.names.slice(0, count)
}
// arguments + 闭包 方式
function addMethod(obj, name, fn) {
var old = obj[name]; // 保存着上一次的添加方法
obj[name] = function() { // 重写obj[name]方法
var isNumber = typeof arguments[0] === ‘number’;
var isEqual = arguments.length === fn.length;
// 这里还可以编写你想要的条件,就例如isNumber
if(isNumber || isEqual){ // 根据透传的参数length与fn方法预期的参数length一直,则执行
return fn.apply(this, arguments);
} else if(typeof old === ‘function’) { // 否则且old类型为function,继续根据闭包链去找
return old.apply(this, arguments);
}
}
}
addMethod(people, ‘find’, find);
addMethod(people, ‘find’, find1);
addMethod(people, ‘find’, find2);
addMethod(people, ‘find’, find3);
people.find(); // ["张一", "张二", "张三", "张四", "李一", "李二", "李三", "李四"]
people.find(‘张’); // ["张一", "张二", "张三"]
people.find(‘李’, ‘四’) // [‘李四’]
people.find(3) // ["张一", "张二", "张三"]
” title=”” data-original-title=”复制”>
var people = {
names: ["张一", "张二", "张三", "张四", "李一", "李二", "李三", "李四"]
};
// 找全员工
function find() {
return this.names;
}
// 全量员工中,找到名字中带有特殊”字“的员工
function find1(name) {
return this.names.filter(item => item.includes(name));
}
// 全量员工中,找到名字中带有多个特殊"字"的员工
function find2(name1, name2) {
return this.names.filter(item => item.includes(name1) && item.includes(name2));
}
// 全量员工的前 count 名
function find3(count) {
return this.names.slice(0, count)
}
// arguments + 闭包 方式
function addMethod(obj, name, fn) {
var old = obj[name]; // 保存着上一次的添加方法
obj[name] = function() { // 重写obj[name]方法
var isNumber = typeof arguments[0] === 'number';
var isEqual = arguments.length === fn.length;
// 这里还可以编写你想要的条件,就例如isNumber
if(isNumber || isEqual){ // 根据透传的参数length与fn方法预期的参数length一直,则执行
return fn.apply(this, arguments);
} else if(typeof old === 'function') { // 否则且old类型为function,继续根据闭包链去找
return old.apply(this, arguments);
}
}
}
addMethod(people, 'find', find);
addMethod(people, 'find', find1);
addMethod(people, 'find', find2);
addMethod(people, 'find', find3);
people.find(); // ["张一", "张二", "张三", "张四", "李一", "李二", "李三", "李四"]
people.find('张'); // ["张一", "张二", "张三"]
people.find('李', '四') // ['李四']
people.find(3) // ["张一", "张二", "张三"]