【问题标题】:Javascript: Create object methods/properties by looping over an arrayJavascript:通过遍历数组来创建对象方法/属性
【发布时间】:2014-11-05 14:54:53
【问题描述】:

我真正想要的是如下代码:

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 不是我的强项。

谢谢!

【问题讨论】:

    标签: javascript loops object methods


    【解决方案1】:

    您的直觉是正确的,您确实可以自动执行此操作:

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

    这里有两件事在起作用:

    1. 在 JavaScript 中,您可以使用点表示法和属性名称 literal (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 返回一个函数,该函数在调用时使用给定的this 值(上例中的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>

    【讨论】:

    • 哇!谢谢。这不仅解决了我的问题,而且解决了一些问题。你知道,我从不喜欢 Javascript(我更喜欢结构化的语言,比如带有真实类的 python),但是我学得越多,我就越意识到我不喜欢它自己的无知 :)
    • @Apollo:是的,这种情况经常发生。现在我发现当我使用一种不太灵活的语言(比如 Java)工作时,我真的很怀念 JavaScript 的灵活性。 :-)(顺便说一句,如果你想要类似于 JS 中的类的东西,这是我使用的一个助手:code.google.com/p/lineagejs。它仍然是原型继承 [这很棒],但带有一些类的陷阱。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-17
    相关资源
    最近更新 更多