的Javascript:通过遍历数组

问题描述:

什么我真的很为创建对象的方法/属性是类似下面的代码:的Javascript:通过遍历数组

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不是我的特长。

谢谢!

你的直觉是正确的,你确实可以自动完成:

colors.forEach(function(color) { 
    painter[color] = function(tool) { 
     painter.draw(color, tool); 
    }; 
}); 

有在这里工作两件事情:

  1. 在JavaScript中,您可以访问(获取或设置)属性使用点符号和属性名文字obj.foo),或使用括号符号和属性名称字符串obj["foo"])。在后一种情况下,字符串可以是任何表达式的结果,包括变量查找。所以painter[color] = ...分配给它的名字来源于color参数的属性。

  2. 然后,我们使用的事实是,我们创建的函数是对调用迭代函数的闭包,我们给了forEach,所以我们可以在该函数中使用color参数。即使调用迭代函数返回,因为我们创造了通话中的功能,并保持对它的引用,该函数保持对上下文的引用(这是一个关闭在上下文中),所以我们可以依靠color参数在那里。更多关于关闭(在我的博客):Closures are not complicated

但由于painter.draw需要的颜色作为第一个参数和工具作为其第二个,还有,如果你愿意,你可以做到这一点,虽然第二个办法:你可以“curry”的颜色参数为使用Function#bind方法(一ES5功能,可以在越来越小数量的旧引擎来垫高没有它)对painter.draw

colors.forEach(function(color) { 
    painter[color] = painter.draw.bind(painter, color); 
}); 

Function#bind返回功能当被调用时,用给定的调用原始函数值(painter在上面的例子)和你提供给bind任何进一步的参数,随后给予原始任何参数。一个简单的例子可能会做出更加清晰:

function func(a, b) { 
 
    snippet.log("this.name = " + this.name); 
 
    snippet.log("a = " + a); 
 
    snippet.log("b = " + b); 
 
} 
 

 
var o1 = { 
 
    name: "o1" 
 
}; 
 
var o2 = { 
 
    name: "o2" 
 
}; 
 

 
var o1boundfoo = func.bind(o1, "foo"); 
 
var o2boundbar = func.bind(o2, "bar"); 
 

 
o1boundfoo("nifty"); // Shows: 
 
        // this.name = o1 
 
        // a = foo 
 
        // b = nifty 
 

 
o2boundbar("nifty"); // Shows: 
 
        // this.name = o2 
 
        // a = bar 
 
        // b = nifty
<!-- Temporary snippet object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

+1

哇!谢谢。这不仅解决了我的问题,而且解决了一些问题。你知道,我从来没有喜欢过Javascript(我喜欢像真正类的python这样的更多结构化语言),但是我学得越多,我越认识到我自己的无知,我不喜欢:) – Apollo 2014-11-05 17:49:10

+0

@Apollo:是的,发生了这样的事情许多。现在我发现,当我用一种不太灵活的语言(Java说)工作时,我真的错过了* JavaScript的灵活性。 :-)(顺便说一下,如果你想要的东西就像JS中的类一样,下面是我使用的帮助器:http://code.google.com/p/lineagejs/。它仍然是原型继承[这很棒],但是带有一些课堂的特征。) – 2014-11-05 18:06:07