作家
登录

让JavaScript 轻松支持函数重载 (Part 1 - 设计)

作者: 来源:www.28hudong.com 2013-03-30 02:25:44 阅读 我要评论

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类,以实现这一设计。

  推荐阅读

  JS 输入字数判断实现代码

判断输入的字数 [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]>>>详细阅读


本文标题:让JavaScript 轻松支持函数重载 (Part 1 - 设计)

地址:http://www.17bianji.com/kaifa2/JS/28315.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)