Javascript 现在最令人不爽的就是函数的重载了 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
undozen
V2EX    Javascript

Javascript 现在最令人不爽的就是函数的重载了

  •  
  •   undozen 2014-05-10 09:52:44 +08:00 4436 次点击
    这是一个创建于 4180 天前的主题,其中的信息可能已经有所发展或是发生改变。
    这还是其他语言里面的概念,JS 里面没有,所以只能自己处理传进来的参数。

    比如 superagent 的主入口:


    function request(method, url) {
    // callback
    if ('function' == typeof url) {
    return new Request('GET', method).end(url);
    }

    // url first
    if (1 == arguments.length) {
    return new Request('GET', method);
    }

    return new Request(method, url);
    }

    这里要自己去处理 method 可能传入的是 url,url 可能传入的是 callback 这样的情况。当我要代理这个函数的时候,比如说,给 url 统一加 prefix,我得完全 copy 这个函数!至少是处理重载的这部分代码。

    function uest(method, url) {
    var r;

    // callback
    if ('function' == typeof url) {
    r = new request.Request('GET', p(method)).end(url);
    }

    // url first
    else if (1 == arguments.length) {
    r = new request.Request('GET', p(method));
    }

    else r = new Request(method, p(url));

    return augment(r);
    }

    哎~
    16 条回复    2014-06-16 09:54:10 +08:00
    undozen
        1
    undozen  
    OP
       2014-05-10 09:58:56 +08:00
    类似的情况,tj 的代码中经常会有判断函数的 arity 来给不同反应的,也就是函数对象的 length 属性,也就是说比如

    function (a, b, c) {}

    定义时括号中指定了三个参数,那么这个函数的 arity 就是三。

    tj 代码中常通过 arity 来给不同回调。刚才说到的 superagent,如果回调的 arity ==1 就 callback(response); 如果是 2 或以上,就照 node 的惯例 callback(err, response)

    express 中也是,middleware arity 如果是 3 或一下,就是 middleware(req, res, next); 这样,而如果是 4 或以上就说明它是一个处理错误的 middleware,这样去调用 middleware(err, req, res, next)


    我觉得根据 arity 来做不同反应真不算是优雅的解决方案。
    undozen
        2
    undozen  
    OP
       2014-05-10 09:59:42 +08:00
    以上两个是搞 JS 的时候比较烦的两点。有一些相关性,吐槽一下,也想听听大家的意见。
    fundon
        3
    fundon  
       2014-05-10 10:24:28 +08:00
    这是一个折中方案,要保持public API简单轻量灵活,如果不喜欢这种风格,可以拆出几个public API
    ianva
        4
    ianva  
       2014-05-10 11:12:29 +08:00
    也有很多解决这类问题的库,比如这个 https://github.com/Moeriki/overload-js
    之前也想自己整个,但感觉实现起来都不是很优雅
        5
    ianva  
       2014-05-10 11:18:41 +08:00
    个人感觉可以自己封装一个,然后用 sweet.js 实现一个自建语法,最后走 grunt 编译,调试走sourcemap,语法校验的话只要别太离谱就ok,这样来到是比较好的解决办法
    hitsmaxft
        6
    hitsmaxft  
       2014-05-10 11:45:39 +08:00
    弱类型谈什么重载?

    如果需要对参数类型进行匹配, 在函数中进行分发这是常见的做法, 该这么做就这么做.

    见 $()
    snoopy
        7
    snoopy  
       2014-05-10 12:49:21 +08:00
    @hitsmaxft 我也这么认为
    powerfj
        8
    powerfj  
       2014-05-10 15:55:51 +08:00
    有的库的接口这样做是为了保持api的简洁,这样从使用者看来会觉得好像它一个函数啥都能干。然后用的人会觉得简洁,利于库的推广和传播

    平常开发的时候参数一多,用对象做参数就ok了,那种代码里面重载的方式我只能说读起来虐心,写起来估计也虐心,尽量少用的好
    alsotang
        9
    alsotang  
       2014-05-10 17:47:52 +08:00
    楼主去看看 jquery 的入口函数吧
    xcc7624
        10
    xcc7624  
       2014-05-10 20:32:30 +08:00 via Android
    不能重载有一定原因吧!假如能重载
    var foo = function(){};
    var foo = function(arg){};
    这种定义函数的方式就不行了。
    Narcissu5
        11
    Narcissu5  
       2014-05-10 23:21:56 +08:00
    function request(url,options) {
    optiOns= options || {};
    var method = options.method || 'GET'
    if(options.callback){
    return new Request(method,url).end(options.callback);
    } else {
    return new Request(method,url);
    }
    }
    个人觉得这个函数应该这么写。
    这函数,返回的可能end了也可能没有,很糟糕的设计个人觉得
    Narcissu5
        12
    Narcissu5  
       2014-05-10 23:26:51 +08:00
    实际上url这种强制的参数应该放在前面,楼主的这个最大的问题其实就是url可能跑到method上,这样就很乱
    cyr1l
        13
    cyr1l  
       2014-05-11 17:03:47 +08:00
    所以我建议传参用 Object,

    request({
    url :"http://google.com",
    method:"POST",
    callback:callback
    })
    tamamaxox
        14
    tamamaxox  
       2014-05-12 11:12:32 +08:00
    js 就是传Object比较好吧,习惯就好
    jianv3
        15
    jianv3  
       2014-05-13 17:05:43 +08:00
    函数的重载 可以自己 模拟方法
    dcoder
        16
    dcoder  
       2014-06-16 09:54:10 +08:00
    @hitsmaxft 正解,又不是 C++/Java
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2553 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 02:18 PVG 10:18 LAX 19:18 JFK 22:18
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86