让 JavaScript 轻松支持函数重载 (Part 1 - 设计)
来源:互联网 发布:博客论坛群发软件 编辑:程序博客网 时间:2024/06/05 01:17
======================================================
注:本文源代码点此下载
======================================================
javascript支持重载吗?
javascript支持函数重载吗?可以说不支持,也可以说支持。说不支持,是因为javascript不能好像其它原生支持函数重载的语言一样,直接写多个同名函数,让编译器来判断某个调用对应的是哪一个重载。说支持,是因为javascript函数对参数列表不作任何限制,可以在函数内部模拟对函数重载的支持。
实际上,在很多著名的开源库当中,我们都可以看到函数内部模拟重载支持的设计。例如说jquery的jquery.extend方法,就是通过参数类型判断出可选参数是否存在,如果不存在的话就对参数进行移位以确保后面的逻辑正确运行。我相信很多人在写javascript时也写过类似的代码,以求为功能丰富的函数提供一个(或多个)简单的调用入口。
不过做种做法一个根本的问题,那就是违反了dry原则。每个支持重载的函数内部都多出来一段代码,用于根据参数个数和参数类型处理重载,这些代码暗含着重复的逻辑,写出来却又每一段都不一样。此外,这些代码要维护起来也不容易,因为阅读代码时你并不能一眼看出函数支持的几种重载方式是什么,要对重载做出维护自然也困难。
描述重载入口的dsl
我希望能够在javascript中以一种简单的方式来描述重载入口。最好就如同在其它语言中一样,使用函数签名来区分重载入口,因为我认为函数签名就是这方面最好的dsl。我假想中最符合javascript语法的重载入口描述dsl应该是这样子的:
var sum = new overload();
sum.add("number, number",
function(x, y) { return x + y; });
sum.add("number, number, number",
function(x, y, z) { return x + y + z; });
在描述好重载入口与对应函数体后,对sum函数的调用应该是这样子的:
sum(1, 2);
sum(1, 2, 3);
上述代码在我看来非常清晰,也非常容易维护——你可以一眼看得出重载入口的签名,并且要修改或者增加重载入口都是很容易的事情。但是我们遇到了一个问题,那就是javascript里面的函数是不能new出来的,通过new overload()获得的对象一定不能被调用,为此我们只能把overload做成一个静态类,静态方法返回的是function实例:
var sum = overload
.add("number, number",
function(x, y) { return x + y; })
.add("number, number, number",
function(x, y, z) { return x + y + z; });
必要的重载入口支持
想象一下,有哪些常见的javascript函数入口是用上述dsl无法描述的?我所知道的有两种:
任意类型参数
假想我们要写一个each函数,对于array就迭代它的下标,对于其它类型就迭代它的所有成员,这两个函数入口的参数列表如何声明?如果用c#,我们会如此描述两个函数入口:
void each(ienumerable iterator) { }
void each(object iterator) { }
然而在javascript当中,object不是一切类型的基类,(100) instanceof object的结果为false,所以我们不能用object来指代任意类型,必须引入一个新的符号来指代任意类型。考虑到这个符号不应该与任何可能存在的类名冲突,所以我选择了用"*"来表示任意类型。上述c#代码对应的javascript应该是这样子的:
var each = overload
.add("array",
function(array) { })
.add("*",
function(object) { });
任意数量参数
在javascript的函数里面,要求支持任意数量参数是很常见的需求,相信使用率比c#里面的params关键字要多得多。在我们之前制定的规则当中,这也无法描述的,因此我们要引入一个不和类名冲突的符号来表示c#中的params。我选择了用"..."表示params,意思是这里出现任意多个参数都是可以接受的。让我们看看jquery.extend的重载应该如何描述:
var extend = overload
.add("*, ...",
function(target) { })
.add("boolean, *, ...",
function(deep, target) { });
小结
在这篇文章当中,我们尝试设计出一种适用于javascript且易读易维护的函数重载写法。在下一篇文章当中,我们将会尝试编写overload类,以实现这一设计。如果你不希望错过的话,欢迎订阅:
cat in dotnet (feed)
cat inchinese (feed)
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
- 让JavaScript 轻松支持函数重载Part 1 - 设计
- 让 JavaScript 轻松支持函数重载 (Part 1 - 设计)
- 让 JavaScript 轻松支持函数重载 Part 2 - 实现
- javascript不能支持函数的重载
- JavaScript的函数支持重载吗?
- JavaScript的函数支持重载吗?
- 让NUnit轻松支持.NET 2.0
- javascript模拟函数重载
- javascript 函数重载
- javascript 模拟函数重载
- Javascript实现函数重载
- JavaScript不支持函数重载
- javascript不支持函数重载
- javascript 重载函数
- JavaScript 函数重载
- javascript函数重载
- javascript函数重载(二)
- JavaScript模拟函数重载
- PHP调用java的class
- Forrest Liu
- jQuery Ajax 方法调用 Asp.Net WebService 的详细例子(原创)
- 面朝大海,春暖花开
- Java学习从入门到精通
- 让 JavaScript 轻松支持函数重载 (Part 1 - 设计)
- html5 WebWorkers 防止浏览器假死
- delphi 的 pos 函数 对中文支持不好。
- java中的输入输出(转载)
- java与c++在虚函数方面的异同
- Ajax三级联动菜单(转载)
- javascript循环性能大比拼
- 深度解析工业图形专家(VG)在delphi中的使用
- Delphi for PHP Update 1推出了