JavaScript中匿名函数的占位符

Placeholders for anonymous functions in JavaScript

本文关键字:占位符 函数 JavaScript      更新时间:2023-09-26

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

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

有没有任何方法可以模拟Scala的占位符语法,这将允许我编写以下内容:

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

显然,getter需要被告知要应用的特定参数名称,或者可以定义一种"元getter",它用一个匿名函数来响应,该函数获取所需的命名属性。

我很想知道CoffeeScript中是否存在类似的内容。ES6 lambda函数更接近,但仍然不如占位符语法那样语义清晰。

您没有说明希望在什么环境中运行,因此,假设出血边缘是可以的,让我们使用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宏来生成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中使用value,你会做正确的事情,并将参数重命名为value$some-integer,以避免匿名函数中的任何名称冲突。(

它确实处理方法调用,但当然,这些方法都不能将占位符用作函数参数:

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

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

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是否能做得更好。