Сокращаем JavaScript код

1 октября, 2008
javascript call

Эта заметка о приеме, который позволяет сократить количество JavaScript кода и сделать его легко читаемым.

Представьте такую ситуацию. В зависимости от значения полученного параметра вы должны вызвать один из методов класса. Набор возможных значений заранее определен и для каждого из них существует метод.

Чтобы не быть голословным, приведу пример такого класса.

  1. function Fruits() {
  2.     this.apples = 10;
  3.     this.oranges = 20;
  4.     this.pears = 30;
  5. }
  6.  
  7. Fruits.prototype.get_apples = function() {
  8.     return this.apples;
  9. }
  10.  
  11. Fruits.prototype.get_oranges = function() {
  12.     return this.oranges;
  13. }
  14.  
  15. Fruits.prototype.get_pears = function() {
  16.     return this.pears;
  17. }

Создать экземпляр этого класса можно так:

  1. var f = new Fruits;

Предположим, что пользователь видит перед собой форму с выпадающим списком, в котором может выбрать название фрукта.

Нам нужно написать функцию-обработчик, которая будет возвращать количество фруктов.

Для этого мы определяем, какой пункт списка (фрукт) выбрал пользователь, и сохраняем его название в переменной curFruit. Теперь нужно вызвать соответствующий метод.

Первое решение, которое напрашивается само собой – использовать операторы switch или if.

Т.е. написать что-то вроде:

  1. switch (curFruit) {
  2.     case "apples" :
  3.         f.get_apples();
  4.         break;
  5.     case "oranges" :
  6.         f.get_oranges();
  7.         break;
  8.     case "pears" :
  9.         f.get_pears();
  10.         break;
  11.     default :
  12.         alert("unknown");
  13. }

Безусловно, этот код работать будет, но есть более элегантное решение:

  1. if (typeof f["get_" + curFruit] == "function") {
  2.     f["get_" + curFruit]();
  3. }
  4. else {
  5.     alert("unknown");
  6. }

Разберем его подробнее. На JavaScript к любому методу класса можно обратиться как к элементу массива. Т.е. f["get_apples"]() работает точно также как и f.get_apples().

Смысл в том, что в названии элемента массива – это обычная строка, и для ее формирования можно использовать любые переменные (в данном случае к приставке "get_" мы добавляем curFruit).

Теперь взгляните на использование оператора typeof. Он просто возвращает тип объекта. В данном примере мы используем его для того, чтобы определить существует выбранный метод или нет.

Очень важно. При использовании typeof можно легко ошибиться. Посмотрите на следующие две строки.

  1. typeof f["get_" + curFruit] //возвращает "function"
  2. typeof f["get_" + curFruit]() //возвращает "number"

или

  1. typeof f.get_apple //возвращает "function"
  2. typeof f.get_apple() //возвращает "number"

В первой строке оператору typeof передан метод класса, во второй – значение, которое этот метод возвращает (т.е. число 10). Разница только в круглых скобках в конце выражения.

Главное преимущество этого приема в том, что вам не нужно изменять функцию-обработчик при добавлении новых методов класса.

Все вопросы и замечания – пишите в комментариях.

До встречи!

Понравилась статья? Подписывайтесь на продолжение rss link !

Или на мой твиттер twitter link

]]>

Добавьте эту страницу в google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

]]>

Опубликовано в JavaScript, Web разработка View Comments

]]>
  • Вероятно, имелся ввиду паттерн проектирования абстрактная фабрика.

    Интересно, как именно Scratch предлагает его использовать в этом примере? (правильный ответ - никак, он тут не подходит без полного перепроектирования).
  • Спасибо за ссылку. Но я не совсем понимаю что тут можно перепроектировать. Пример ведь написан для того, чтобы показать особенности JS. Точнее то, что к методу объекта можно обратиться как к элементу массива.
    На мой взгляд, чтобы был смысл в Factory нужно вообще другой пример подобрать. Объект ведь в данном случае один, а Factory паттерн предназначен для создания разных объектов и при этом у них должны быть методы с одинаковыми именами. Здесь обратная ситуация.
  • Я новичок, и мне тяжело понять про фабрику... я слыхала на плюсах есть такое. оказывается и здесь тоже..Только все равно тяжело понять. Вижу я здесь не одна такая)
  • действительно подробней про фабрику если можно
  • Что-то я тоже про фабрику не понял не много!
  • типичные методы объекто-ориентированного программирования + особенности, характерные именно для javascript. Cпасибо за статью, буду применять на практике.
  • Хм... Фабррика?
  • Честно говоря, не понял. Какая фабрика?
  • Чистяков Денис
    Ой, пардон ссылка вставилась не так как хотел, подправь, если не сложно.
  • Исправил, надеюсь правильно :-)
  • Чистяков Денис
    Да, спасибо.
    Там в принципе три статьи, как минимум повещены JavaScript, все очень стоящие и все актуальны и сейчас хотя написаны достаточно давно.
    Котерова, вообще интересно читать и очень познавательно, для PHP, Perl и JS разработчиков.
  • Чистяков Денис
    Подход интересный и полезный, но лично мне больше импонирует другой способ создания «классов» в JavaScript'ах — не через использование прототипов, а через прямое создание методов:

    // Конструктор.
    function NewClass() {
    this.property = 123;
    // Создаем методы класса прямо в конструкторе.
    this.method1 = function(x) {
    alert("Вызван method1("+x+")");
    }
    // То же самое.
    this.method2 = function(x) {
    alert("Вызван method2("+x+")");
    this.method1();
    }
    }

    // Создаем объект и проверяем работу.
    var obj = new NewClass();
    obj.method1(10);


    подробнее: Большие хитрости JavaScript

    Это ничего принципиально не меняет в идее предложенной вами, но реализовывать удобнее )
  • Да, способ удобный. Почему-то не встречал его раньше. Вообще мне никогда не нравилось, что на JavaScript код класса можно разбросать по всему скрипту.

    Кстати, отличная статья!
  • Хороший подход и правильный! Как всегда отличная заметка :)
blog comments powered by Disqus ]]>