我一直在编写d3
代码,最终会有很多这样的函数:
selection.attr('x', function(d) { return d.layout.x; });
有没有办法模拟Scala的占位符语法,这将允许我写这个:
selection.attr('x', _.layout.x);
显然,需要告诉getter要应用的特定参数名称,或者可以定义一种“meta-getter”,它使用获取所需命名属性的匿名函数进行响应。
我有兴趣知道是否存在类似这样的东西,例如CoffeeScript。 ES6 lambda函数更接近,但仍然不像占位符语法那样具有语义和清晰度。
答案 0 :(得分:2)
你不能说出你希望它运行的环境,因此,假设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)
执行此操作举个例子)。此外,它需要一个明确的$
来表示链的末尾。但对于简单的吸气剂,它的效果非常好。
或者,如果您现在需要支持不是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 do the right thing中使用value
并将参数重命名为value$some-integer
以避免匿名函数内的任何名称冲突。)
它确实处理方法调用,但当然这些方法都没有处理使用占位符,例如函数参数:
selection.attr('x', someFunction(_));
答案 1 :(得分:1)
这可以使用函数而不是对象进行模拟:
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能否做得更好。