【问题标题】:Placeholders for anonymous functions in JavaScriptJavaScript 中匿名函数的占位符
【发布时间】:2014-06-12 05:51:36
【问题描述】:

我一直在编写d3 代码,最终有很多这样的功能:

selection.attr('x', function(d) { return d.layout.x; });

有什么方法可以模拟 Scala 的占位符语法,我可以这样写:

selection.attr('x', _.layout.x);

显然,getter 需要被告知要应用的特定参数名称,或者可以定义一种“meta-getter”,以获取所需命名属性的匿名函数进行响应。

我很想知道类似的东西是否存在于例如 CoffeeScript 中。 ES6 lambda 函数更接近,但仍不如占位符语法语义和清晰。

【问题讨论】:

    标签: javascript scala d3.js


    【解决方案1】:

    你没有说你想让它在什么环境下运行,所以,假设the bleeding edge没问题,我们就用Proxy

    var _ = new Proxy({}, {
        get: function(target, name) {
            return createProxyForPath(name, []);
        }
    });
    
    function createProxyForPath(name, path) {
        var newPath = path.slice();
        newPath.push(name);
        return new Proxy({}, {
            get: function(target, name) {
                if (name !== "$") return createProxyForPath(name, newPath);
                return function getter(obj) {
                    return newPath.reduce(function(prev, curr) {
                        return prev[curr];
                    }, obj);
                };
            },
            apply: function(target, context, args) {
              // TODO: Preserve function calls and args here
            }
        });
    }
    

    你会这样使用它:

    > [{x: 1}, {x: 2}, {x: 3}].map(_.x.$)
    [1, 2, 3]
    

    它并不能完全替代 Scala 的神奇下划线(例如,它现在不会捕获方法调用,因此您不能以 _.x.toString().slice(0, 3) 为例)。此外,它需要一个显式的$ 来表示链的结束。但对于简单的 getter 来说,它工作得很好。

    或者,如果您现在需要支持不是 Firefox 的浏览器,您可以编写 sweet.js macro 来生成 getter:

    // Via Daniel
    macro _ {
      rule { . $m ... } => { function (value) { return value.$m ... } }
    }
    
    selection.attr('x', _.layout.x + 1);
    

    将扩展为:

    selection.attr('x', function(value) {
      return value.layout.x + 1;
    });
    

    (如果你自己在函数 sweet.js 中使用 valuedo the right thing 并将参数重命名为 value$some-integer 以避免匿名函数内部的任何名称冲突。)

    它确实处理方法调用,但当然这些方法都没有使用占位符作为函数参数来处理:

    selection.attr('x', someFunction(_));
    

    【讨论】:

    • 这很酷,感谢您向我介绍 Proxy。我没有指定环境,因为我是出于好奇而询问的;我认为我实际上不会在与任何人共享的代码中使用这些方法中的任何一种:P。也许当 ES6 变得司空见惯...
    • 一旦我 learned how 为此编写了一个宏,我会将它添加到您的答案中并接受:)。
    • @DanielBuckmaster - 你太棒了 - 非常感谢你也引入了宏!
    • 自动重命名很好。好吧,我想我们刚刚解决了这个问题!
    【解决方案2】:

    这可以用函数而不是对象来模拟:

    var getter = function(properties) {
      props = properties.split('.');
      return function(d) {
        return props.reduce(function(prev, curr) {
          return prev[curr];
        }, d);
      };
    };
    
    selection.attr('x', getter('layout.x'));
    

    这……好吧,但我想知道 JS 是否可以做得更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2011-06-24
      • 2010-11-06
      • 2011-07-26
      • 2011-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多