js的重载

JavaScript09

js的重载,第1张

问:什么是重载?

答:同样的函数,不同样的参数个数。

《JS高级程序设计》里是提到过函数是没有重载的,ts中有重载。但是可以根据arguments的长度来实现重载。

最后定义的fn将前两个fn覆盖掉,所以没有达到重载的效果

虽然上述达到了想要的效果,但不是完美的实现js的重载。

高端实现js的重载做法是利用闭包。

参考资料: https://www.cnblogs.com/yugege/p/5539020.html

所谓 函数重载(method overloading) ,就是函数名称一样,但是输入输出不一样。或者说,允许某个函数有各种不同输入,根据不同的输入,返回不同的结果。凭直觉, 函数重载 可以通过 if…else 或者 switch 实现,这就不去管它了。jQuery之父John Resig提出了一个非常巧(bian)妙(tai)的方法,利用了闭包。

从效果上来说, people 对象的 find 方法允许3种不同的输入: 0个参数时,返回所有人名;1个参数时,根据firstName查找人名并返回;2个参数时,根据完整的名称查找人名并返回。

难点在于, people.find 只能绑定一个函数,那它为何可以处理3种不同的输入呢?它不可能同时绑定3个函数 find0 , find1 find2 啊!这里的关键在于 old 属性。

由addMethod函数的调用顺序可知,people.find最终绑定的是find2函数。然而,在绑定find2时,old为find1;同理,绑定find1时,old为find0。3个函数find0,find1与find2就这样通过闭包链接起来了。

根据 addMethod 的逻辑,当 f.length arguments.length 不匹配时,就会去调用 old ,直到匹配为止。

都知道在js中没有办法直接实现方法重载,因为在js中如果定义了多个名称相同,但参数个数不一样的方法,其实只有最后一个方法能被真正调用,其他的方法都被覆盖掉了。

但每一个函数都有一个特殊的参数arguments,利用它可以实现方法的重载。

例如:

复制代码

代码如下:

function

Add(firstnumber,sencondnumber)

{

return

firstnumber+sencondnumber

}

只能处理两个参数,如果有多个参数,或者没有参数,一个参数的情况都是处理不了的。如果没有传递参数,则firstnumber,sencondnumber都是未定义的,如果传递了一个参数,就相当于只给firstnumber赋值了,sencondnumber依然是未定义。相反如果传递了多于两个的参数,则相当于firstnumber,sencondnumber都赋值了,虽然还有其他的参数,但处理时都忽略掉了。如果能获取其他的参数,自然就可以处理了。此时应该就可以想到函数的特殊参数arguments,这个包含了传递给函数的所有参数,利用它就可以实现方法重载的效果。

以上的方法修改如下:

复制代码

代码如下:

function

Add(firstnumber,sencondnumber)

{

if

(arguments.length

==

0)//没有传递参数

{

return

null

}

else

if

(arguments.length

==

1)

{//传递的是一个参数

return

firstnumber//也可以写为

return

arguments[0]

}

else

if(arguments.length

==

2)//传递的是两个参数

{

return

firstnumber+sencondnumber//也可以写为

return

arguments[0]+arguments[1]

}

else

{

var

total=0

for

(var

i

=

0

i

<

arguments.length

i++)

{

total=total+arguments[i]

}

return

total

}

}

当然这种方法的弊端就是参数的顺序不能打乱,如果函数实现依赖于参数的顺序,就必须进行特殊处理,例如传递null来占位。

由于传递给函数的参数是严格按照定义函数的顺序给每一个参数赋值的,如果只想给第二个参数赋值,则必须传递两个参数,否则实际上传递的值赋值给了第一个参数,并没有赋值给第二个参数。

例如只想给sencondnumber传值,但不想给firstnumber传值,必须这样调用Add(null,2)(当然函数内部必须处理传递特殊值的情况),如果这样调用Add(2),其实是给firstnumber传值了,相当于调用了传递了一个参数的情况。