V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
sunjourney
V2EX  ›  JavaScript

es6 使用了默认参数的函数无法被 currying,坑啊!

  •  
  •   sunjourney · 2017-03-20 00:08:45 +08:00 · 2362 次点击
    这是一个创建于 2595 天前的主题,其中的信息可能已经有所发展或是发生改变。

    记得之前看 MDN 文档,上面写在 es6 之前要给函数默认参数的写法是:

    var add = function (x, y) {
      x = (typeof b !== 'undefined') ?  x : 1
      return x + y
    }
    

    在 node 下给 var add = function (x = 1, y) blabla 做 currying ,报错了。。。怎么会呢?

    百思不得骑姐,用 babel 试试吧,结果竟然是:

    var add = function add() {
      var x = arguments.length <= 0 || arguments[0] === undefined ? 'oo' : arguments[0];
      var y = arguments[1];
      return x + y;
    };
    

    难怪不能 currying 。大呼 MDN 误我!赶紧去翻 MDN ,准备发贴开喷!!!

    OMG , MDN 文档才发现写的居然是“一种常用的策略”:

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters

    好吧,我认栽了!但是转念一想, es6 和 bebel 的默认参数写法为啥不直接用 typeof 的思路呢?这样就不能做 currying 了

    11 条回复    2017-03-28 17:43:55 +08:00
    ctsed
        1
    ctsed  
       2017-03-20 01:21:59 +08:00
    var add = function (y, x=1) {
    x = (typeof b !== 'undefined') ? x : 1
    return x + y
    }

    -- or --

    var add_c = function (y) {
    return add(x=1, y)
    }
    sunjourney
        2
    sunjourney  
    OP
       2017-03-20 08:48:19 +08:00
    @ctsed 这是手动 currying , 用 curry function 就不行了呢
    lovedebug
        3
    lovedebug  
       2017-03-20 10:00:09 +08:00
    默认参数柯里化? add 是个函数表达式,做柯里化不是应该对带参数的 add 做吗?
    sunjourney
        4
    sunjourney  
    OP
       2017-03-20 10:06:59 +08:00
    @lovedebug #3 如果默认参数是用 typeof 去实现,不消弥掉 arguments 的参数, underscore, lodash 的 curry 就可以对函数做 currying ,但如果是 babel 这种消弥掉默认 arguments 的方法,就无法判断 fn.length, currying 库的方法就不能用了,自己实现 currying 目前也没找到能用的方法
    lujjjh
        5
    lujjjh  
       2017-03-20 10:47:33 +08:00   ❤️ 1
    https://lodash.com/docs/4.17.4#curry

    _.curry(func, [arity=func.length])

    The arity of func may be specified if func.length is not sufficient.

    不过话说回来,有默认参数做 currying 的感觉很奇怪
    sunjourney
        6
    sunjourney  
    OP
       2017-03-20 11:00:56 +08:00
    @lujjjh #5 Thanks ,没仔细看文档,原来还可以通过指定 arity 实现,哎,我自己写的 currying 想支持 curry function with partial arguments (ex: const add100 = curry(add, 100),看来是没法做 lodash arity 的支持,如果真的用 typeof 的方法做默认参数就没问这种烦恼。问题来了 typeof 和 arguments.length 两种优劣如何呢?何以最终实现是用 arguments.length 呢
    sunjourney
        7
    sunjourney  
    OP
       2017-03-20 11:10:48 +08:00
    @lujjjh #5 真遇到那种有默认参数的函数,没看源码, currying 又不报错,调用来报错,很无语
    lujjjh
        8
    lujjjh  
       2017-03-20 11:13:08 +08:00   ❤️ 1
    @sunjourney 你举的「 curry function with partial arguments 」的例子,完全可以写成
    const add100 = curry(add)(100)

    不用 arguments.length 没法区分是没传还是传了 undefined
    sunjourney
        9
    sunjourney  
    OP
       2017-03-20 11:54:39 +08:00
    @lujjjh #8 感谢解惑!
    8qwe24657913
        10
    8qwe24657913  
       2017-03-28 17:38:49 +08:00
    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/length
    length 是必须传入的参数个数,默认参数是可选的,所以其之后的参数也是可选的,不算在 length 里
    sunjourney
        11
    sunjourney  
    OP
       2017-03-28 17:43:55 +08:00
    @8qwe24657913 #10 嗯呢,大部分的 es6 的书或文档貌似都没有提这些规范,总想给人 es6 有大动作的新鲜感,深入点的细节变动都不涉及,这些坑不踩踩都不行呢。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   905 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 21:32 · PVG 05:32 · LAX 14:32 · JFK 17:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.