你没有说你想让它在什么环境下运行,所以,假设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 中使用 value 将 do the right thing 并将参数重命名为 value$some-integer 以避免匿名函数内部的任何名称冲突。)
它确实处理方法调用,但当然这些方法都没有使用占位符作为函数参数来处理:
selection.attr('x', someFunction(_));