2014-11-05 8 views
1

Что я действительно ищет это код вроде следующего: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 не моя сильная сторона.

Спасибо!

ответ

2

Ваш инстинкт правильно, вы можете действительно автоматизировать:

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>

+1

Wow! Благодарю. Это не только решает мою проблему, но и устраняет некоторые вещи. Вы знаете, мне никогда не нравился Javascript (я предпочитаю более структурированные языки, такие как python с реальными классами), но чем больше я узнаю, тем больше я осознаю свое собственное невежество, которое мне не нравится :) – Apollo

+0

@Apollo: Да, это происходит много. Теперь я нахожу, когда я работаю на менее гибком языке (Java, скажем), я очень скучаю по гибкости JavaScript. :-) (Кстати, если вам нужны вещи, похожие на классы в JS, вот помощник, который я использую: http://code.google.com/p/lineagejs/. Это все еще прототипическое наследование [это замечательно], но с с некоторыми атрибутами класса.) –

 Смежные вопросы

  • Нет связанных вопросов^_^