Настоящий JavaScript шаблон, который я использую для веб-проектов.

  Автор статьи: Louis Lazaris   Оригинал:http://www.impressivewebs.com/my-current-javascript-design-pattern/

Всегда, работая над важным JavaScript проектом, я, с целью улучшения моих предыдущих результатов, пытался внести что-то новое. На данный момент, начиная новый проект с нуля, я использую различные варианты того, что Эдди Османи (Addy Osmani) и другие относят к категории модульных шаблонов.

Ниже представлена моя версия такого шаблона, который подразумевает использование jQuery. Затем я более детально остановлюсь на всех его частях и объясню, как это применить на практике:

var s,
PrimaryNameSpace = {

settings : {
basicExample: $(‘.main’),
nestedExample : {
first: true,
second: true,
third: true,
fourth: true,
fifth : [‘one’, ‘two’, ‘three’, ‘four’, ‘five’, ‘six’]
},

foo: ‘bar’

},

init: function () {
s = this.settings;

this.nextMethod();
this.anotherMethod();
},

nextMethod: function () {
},

anotherMethod: function () {
}

};

$(function () {
PrimaryNameSpace.init();
});

Теперь давайте рассмотрим структуру кода и узнаем почему я считаю такой шаблон предпочтительным с точки зрения удобства в использовании.

Большая часть кода используется для создания тела объекта, образуя при этом пространство имен. Это основное пространство имен содержит определенные в нем методы и группу значений — настроек settings. Давайте начнем с настроек.

Объект settings

Объект settings заключает в себе кэшируемые значения и объекты, которые я планирую использовать в рамках всего шаблона. Что касается других настроек, которые не кэшируются, то их значения зависят от различных факторов, поэтому они будут объявлены с начальным значением null.

Для того, чтобы получить доступ к объекту настроек из тела метода init, необходимо использовать конструкцию this.settings. То есть, касательно моего примера, если мне необходимо извлечь значение первого кэшируемого объекта, то это будет выглядеть примерно так:

console.log(this.settings.basicExample);

Но эта форма представления слегка запутанна. Поэтому я, как вы вероятно заметили, сохранил необходимое значение в переменной s. Таким образом, я смогу получить доступ ко всем моим настройкам через свойства объекта s.

Как видно из примера, значения определенной категории настроек могут быть реализованы в виде отдельного вложенного объекта, содержащего набор свойств. Имея переменную s, мы можем получить значение вложенной настройки, используя вот эту конструкцию — s.nestedExample.second.

Должен признать, что я достаточно долго считал, что объект s должен определяться внутри каждого метода. Но, как выяснилось позже, благодаря справедливым замечаниям участников обсуждения этой темы, достаточно лишь одного определения значения для этой переменной в первом методе, так как область ее видимости находится в пределах всего внешнего объекта и ее значение доступно из любого метода объекта. И еще одна корректура: Как было замечено Реем Банго, переменная s должна объявляться за пределами индивидуальных методов, при этом нет необходимости делать ее глобальной, и она будет доступна везде в пределах основного объекта (*PrimaryNameSpace).

Метод init

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

Кроме того, метод init выполняется самым первым (в нижней части примера он вызывается раньше всех других методов). После его успешного выполнения можно инициализировать выполнение других методов.

Если остальные методы не имеют каких-либо зависимостей от первого — init, то я могу обращаться к ним вне родительского объекта так, как я это делаю с методом init. В противном случае, если вы должны передать другим методам какие-либо аргументы из метода init, то лучше запускать их в рамках первого метода.

Специализированные методы.

Методы, следующие за init, по сути своей будут выполнять более специализированные функции. К примеру, если у меня возникает необходимость в манипуляции с хэшами в URL, то я, возможно, вызову метод с именем типа getHash или doHash.

То есть все, что я могу выделить в отдельно стоящую специальную функцию, или то, что Крисс Койер называет «отдельным куском функциональности», я могу определить как отдельный метод. (Хотя я планировал написание этого поста раньше, но именно статья Крисса вдохновила меня на это.)

Вызов методов внутри других методов.

Каждый метод может быть вызван в любом месте следующим образом — PrimaryNameSpace.nextMethod(). Но используя метод в рамках другого метода, я могу просто использовать this.nextMethod().

Единственным исключением может быть ситуация, когда внутри метода определен другой контекст. Если вы используете ключевое слово this в контексте текущего метода, то вы ссылаетесь на его родительский объект. Но если, к примеру, в рамках метода вы, используя возможности jQuery, с помощью анонимной функции вызываете callback-функцию, тогда значение this будет изменено на то, которое определяется контекстом используемой анонимной функции. То есть, если мне необходимо вызвать один из своих методов внутри анонимной функции, то я должен использовать полную форму: PrimaryNameSpace.nextMethod().

Буду рад вашим комментариям.

Для более опытных JavaScript разработчиков изложенный здесь материал покажется слишком тривиальным. Но я не претендую на звание JavaScript эксперта. Более того, при обсуждении отдельных областей этого языка, я чувствую себя очень неуверенно. Поэтому отнеситесь к изложенному с должной долей скептицизма. И в том случае, если вы найдете предложенный мной код не аккуратным с технической точки зрения или у вас есть предложения по улучшению этого шаблона, то я с удовольствием прислушаюсь к вашим советам.

И не стесняйтесь поделится своими вариантами JavaScript шаблонов, которые вы считаете более предпочтительными.

Обновления к статье:

Отличная идея была предложена Джозефом Силбером касательно определения переменной s. В моем случае она определяется за пределами пространства имен основного объекта, то есть является глобальной. Заключая все содержимое в рамки самовыполняющейся анонимной функции, вы добиваетесь локализации всех используемых значений.

Крисс Койер в своей новой статье «Как вы структурируете ваш Javascript код? Вариант модульного шаблона» идет дальше в этом отношении.

*Луис Лазарис действительно лишь поверхностно затронул вопрос модульных JavaScript шаблонов в веб-дизайне. Более детально эта и другие смежные стороны использования JavaScript рассматриваются в упомянутых здесь статьях Крисса Койера, перевод которых будет представлен вашему вниманию ближайшее время. Данную статью можно, скорее всего, расценивать как отправную точку для более глубоких профессиональных исследований в этом направлении.

* Примечание переводчика.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *