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 · 3981 次点击
    这是一个创建于 3641 天前的主题,其中的信息可能已经有所发展或是发生改变。
    这还是其他语言里面的概念,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
    之前也想自己整个,但感觉实现起来都不是很优雅
    ianva
        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   ·   我们的愿景   ·   实用小工具   ·   1261 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 17:50 · PVG 01:50 · LAX 10:50 · JFK 13:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.