有时候我们会在javascript中调用方法时, 只要方法名写对了, 即使参数列表不对也可以正常调用. 当然是不是跟你预想的一样工作时另外一回事儿. 本来倒是没注意这个现象, 因为我每次在js中调用方法时都是严格安装输入的参数列表来传数据的, 也没有吧两个js方法使用相同的命名, 但是刚好今天一个同事遇到了, 所以就来研究一下.
首先, js中的方法调用仅仅是看方法名, 对于参数列表对不对应一律不管. 也就是说你可以在页面中用GetAlert()来调用GetAlert(content)方法, 也可以使用GetAlert('a')来调用GetAlert()方法。如:
<input type="button" onclick="GetAlert()" value="argu0" /> function GetAlert(content) { alert("有参数,参数是" + content + "!"); }
当然, 这样调用时获取不到参数的, 所以content会显示为undefined.
那么有人可能会问:如果我方法传了参数, 但是方法中没有接受的参数怎么办呢?
针对这个问题, 我们可以在方法的内部用arguments来接收传入的参数. 实际上使用很简单, 接收第i个参数就是用arguments[i-1]来接收即可.
第二个问题, 如果js中同时有两个同名的方法, 那会调用谁呢, 是调用其中的一个, 还是根据参数列表来相应的调用呢. 请见下例:
<input type="button" onclick="GetAlert()" value="argu0" /> function GetAlert() { alert("没有参数!"); } function GetAlert(content) { alert("有参数,参数是" + content + "!"); }
实际运行之后你就会发现, 它调用的不是和它相对应参数的那个方法, 而是后一个. 这个也很好理解: 因为js中不允许有重名的方法存在, 所以在解析到后一个方法时, 会将前一个方法覆盖掉. 所以无论你怎么调用, 只能调用后面的方法.
现在到了第三个问题了, 就是方法的重载.
我们都很熟悉了C#中的重载, 现在来复习下: C#中重载的特点是:两必须一可以:
- 方法名必须相同
- 参数列表必须不同
- 返回值可以不同也可以相同 (实际上就是和返回值不相关)
那么js中因为不能有两个方法名相同, 所以第一条肯定不能实现. 这也就说明了在js中没有办法实现像C#那样的重载了。但是我们看看在jquery中有些方法, 实现的似乎和重载一样, 如val()和val(''). 它是怎么实现的呢,答案就是刚才第一点中提到的arguments。
通过下面的例子你就可以很明白的看出来是如何通过arguments来迂回的实现js的重载的:
function GetAlert() { if (arguments.length == 0) { alert("没有参数!"); } else if (arguments.length == 1) { var str = arguments[0].constructor; if (arguments[0].constructor == String) { alert("有一个String型参数,参数是" + arguments[0] + "!"); } else if(arguments[0].constructor ==Date) { alert("有一个Date型参数,参数是" + arguments[0].toString() + "!"); } } else { var argu = ""; for (var i = 0; i < arguments.length; i++) { argu = argu + arguments[i] + ","; } alert("有大于一个的参数,参数是" + argu + "!"); } }
看完了这个js方法相信大家都明白了, 原来是通过arguments.length和arguments[].constructor来实现区别参数的。这时调用起来就似乎实现了重载的功能:
<input type="button" onclick="GetAlert()" value="argu0" /> <input type="button" onclick="GetAlert('a')" value="argu1Str" /> <input type="button" onclick="GetAlert(new Date())" value="argu1Date" /> <input type="button" onclick="GetAlert('a','b')" value="argu2" />
最后需要提醒一点, 虽然我们实现了重载功能, 但是你也看到了, 这样写的代码是很多且判断很多, 所以尽量少用这种代码来实现重载功能. 有时候我们需要问问自己:这个地方一定要用重载么?
下面附上了本次的测试代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Title</title> <script type="text/javascript" > function GetAlert(content) { alert("有参数,参数是" + content + "!"); } function GetAlert() { alert("没有参数!"); } function GetAlert() { if (arguments.length == 0) { alert("没有参数!"); } else if (arguments.length == 1) { var str = arguments[0].constructor; if (arguments[0].constructor == String) { alert("有一个String型参数,参数是" + arguments[0] + "!"); } else if(arguments[0].constructor ==Date) { alert("有一个Date型参数,参数是" + arguments[0].toString() + "!"); } } else { var argu = ""; for (var i = 0; i < arguments.length; i++) { argu = argu + arguments[i] + ","; } alert("有大于一个的参数,参数是" + argu + "!"); } } </script> </head> <body> <input type="button" onclick="GetAlert()" value="argu0" /> <input type="button" onclick="GetAlert('a')" value="argu1Str" /> <input type="button" onclick="GetAlert(new Date())" value="argu1Date" /> <input type="button" onclick="GetAlert('a','b')" value="argu2" /> </body> </html>