文章插图
函数重载
在其他语言中,我们一般都听说过重载的概念,对于一个方法,如果我们期望传入不同的参数类型,或者传入不同的参数个数,甚至传入参数的顺序不一样,而去执行不同的处理代码,以返回相应的结果,那么他们的方法名是可以相同的,而且它们不会产生冲突,这就是所谓的重载 。
这是因为像JAVA等这样的强类型语言,他们具有类型约束和方法签名,这样就使得他们能够根据调用时传入参数的情况来决定使用哪一个同名方法来处理需要的操作 。
是在说我吗?
但是js属于弱类型语言,也就是说它不会规定参数必须传入哪种类型,定义的方法也不具有签名的功能,而且在定义多个同名方法时,类似于css里面的层叠样式表的效果,后定义的同名方法会覆盖前面的方法,还有一个就是函数具有提升的特性,这也就使得它无法实现重载的功能 。
怎么办呢?
其实js中也确实不需要重载的功能,因为没有类型的约束,在一个方法里面就可以做很多自由的发挥,不但能满足需要重载的需求,而且还能玩一些花样 。
不过话又说回来,没有了约束,就容易犯错,都用一个方法体来处理所有情况,就会容易出乱子,使得我们需要使用一堆的类似if-else的语句来做到这一点 。
那么我们能不能在现有js运行方式的基础上,借鉴其他语言对于重载的运用,来绕个弯子变量来实现一下属于js自己的重载方式呢?
试一试
我们今天只讨论在js中变相实现重载的方式,而不讨论它的意义与实际应用场景,我们通过一个简单的例子,来支撑这个讨论,其他的交由你们来自由发挥 。
让我们开始吧
js重载的方式在js中主要有以下几种实现重载的方式:
- 使用剩余参数的形式来接收可变的参数,并通过一些判断手段来处理不同情况的逻辑 。
- 使用arguments的形式,来动态判断需要执行的操作
- 使用proxy的形式来拦截函数的行为,以达到控制不同的逻辑分支 。
前两种方式的优缺点:
优点:可以直接定义函数或使用表达式
缺点:函数名不能相同,需要写较多的判断分支
第三种方式的优缺点:
优点:可以不用写各种参数形式的分支
缺点:只能使用表达式定义函数
【JS中的重载——如何实现一个类似这样的功能,我也想玩玩】由于前两种网上已经有很多的实现思路与方案,因此这里不再进行探讨,其中有很多奇妙的实现,可以做到在js中使用重载的思想 。
所以在此我们只讨论第三种方案,我们下面来看一下它的思路是什么,是否满足重载的需求,它是如何实现的,以及它能满足我们什么样的需求?
这是什么呢?
需求假设我们现在有这样一个场景和需求:
自己开了一家服装店,由于生意火爆,我们想要答谢新老顾客,现在推出了一个活动,全场无论任何服装,只要买一件就直接打95折,只要买两件就全部打9折,只要买三件就全部打85折,只要买四件及以上,就全部打8折 。
如果用代码来实现,其实就是给方法中传入一个两个三个四个参数的问题,因此我们自然而然的就想到了使用重载来实现这个需求 。
接下来我们就试着自己实现一个这样的功能,看看可不可以创建一个赋能方法来使某个业务处理函数具有重载的能力 。
思路分析要生成这样一个赋能方法,我们需要有对函数改造的能力,在创建业务处理函数的时候,最好能够改变它的默认行为,在执行的时候也能够对它进行拦截以做一些额外的操作 。
那么我们很自然而然的就想到了使用Proxy,先生成一个Proxy函数,然后在给它设置属性的时候,我们进行拦截,把赋值操作中的value缓存起来,以备将来调用的时候做分支处理,根据参数的个数与类型来控制需要执行的业务逻辑代码 。它真的能做到吗?我们来看一下下面的一步步代码实现 。
实现需求
function Overload(defaultCall) {let func = defaultCall || new Function()func.overloadCached = []return new Proxy(func, {set(target, prop, value) {if(prop === 'load') {target.overloadCached.push(value)}},Apply(target, thisArg, argumentsList) {for(let i = target.overloadCached.length - 1; i > -1; i--) {if(argumentsList.length === target.overloadCached[i].length || (argumentsList.length > target.overloadCached[i].length)) {return target.overloadCached[i].apply(thisArg, argumentsList)}}return target.apply(thisArg, argumentsList)}})}let sum = Overload()sum.load = function (a) {return a * 0.95;}sum.load = function (a, b) {return (a + b) * 0.9;}sum.load = function (a, b, c) {return (a + b + c) * 0.85;}sum.load = function (a, b, c, d, ...arg) {return (arg.concat(a,b,c,d).reduce((total, cur) => {return total + cur},0)) * 0.8;}console.log(sum(200));console.log(sum(200, 300));console.log(sum(180, 280, 190));console.log(sum(270, 260, 310, 240));console.log(sum(180, 220, 240, 210, 190));//输出:190,450,552.5,864,832
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 文玩|翡翠当中的瑕疵,你都了解多少呢?按照严重程度来分辨是否要买
- 良渚文化|徐梦梅——良渚"玉石文"是殷墟甲骨文之祖
- 5个让人爱不释手的微信小程序,每一款都是精品中的精品
- 瑶医望诊绝技——观目诊病 瑶医目诊
- 星象|星象|Alex大叔 一周宇宙星象播报(8.22—8.28)
- 翡翠手镯|翡翠玉雕中的巧色,分色,俏色你分清楚了吗
- 雕刻|【臻曦文化】瓷器上的艺术手段—雕刻瓷
- 国画技法——山水的几种画法 国画山水技法
- 5岁儿童数学启蒙 生活中的数
- 鸡胸肉|多种类型男生眼中的心动发型