我真正想要的是如下代码:
var painter = {}; // An object to hold methods
var colors = ['blue', 'red', 'green', 'yellow']; // The names of methods to be defined
colors.forEach( function(color) {
painter.defineMethod(color, function(){ console.log(color); });
});
painter.blue() // writes blue
painter.red() // writes red
etc.
painter.defineMethod()是关键。
我必须为一个对象定义几个(超过40个)方法,它们基本上都是相同的,具有微小但可预测的更改,它们实际上都调用另一个方法。例如:
painter.blue = function(tool) {
painter.draw('blue', tool); // Would paint blue with a brush or pencil or whatever.
}
这样的事情是否可能,或者我是否明确地定义了所有这些属性?这种或那种方式有任何性能上的好处吗?
在Javascript中,具有变量变量或魔术方法的语言很容易被证明是困难的(或不可能的)。虽然我承认javascript不是我的强项。
谢谢!
答案 0 :(得分:2)
你的直觉是正确的,你确实可以实现自动化:
colors.forEach( function(color) {
painter[color] = function(tool) {
painter.draw(color, tool);
};
});
这里有两件事情可以解决:
在JavaScript中,您可以使用点表示法和属性名称 literal (obj.foo
)或使用括号表示法来访问(获取或设置)属性属性名称 string (obj["foo"]
)。在后一种情况下,字符串可以是任何表达式的结果,包括变量查找。因此painter[color] = ...
会分配给名称来自color
参数的属性。
然后我们使用这样一个事实,即我们创建的函数是对我们给forEach
的迭代函数的调用的闭包,因此我们可以使用{{ 1}}该函数中的参数。即使对迭代函数的调用返回,因为我们在调用中创建了一个函数并保留了对它的引用,该函数保留了对上下文的引用(它在上下文中是 em color
论证。关于闭包的更多信息(在我的博客上):Closures are not complicated
但是,由于color
将颜色作为第一个参数而工具作为第二个参数,因此,如果您愿意,可以采用第二种方式:您可以" {{3 }}" painter.draw
上使用Function#bind
(一种可以在越来越少的旧引擎上填充的ES5功能)上填充方法的颜色参数:
painter.draw
colors.forEach( function(color) {
painter[color] = painter.draw.bind(painter, color);
});
返回一个函数,该函数在调用时调用具有给定Function#bind
值(上例中的this
)的原始函数以及您提供给{{1的任何其他参数然后是给原始的任何参数。一个简单的例子可能会更清楚:
painter

bind