Изучаем продвинутый JavaScript с помощью исходных кодов Backbone.js

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

В этом посте я поделюсь некоторыми концепциями, которые помогли мне понять как Backbone.js так и JavaScript на более глубоком уровне.

Немедленное исполнение выражений функций (Immediately-Invoked Function Expression)

IIFE выглядит следующим образом:

Замечание: Отктытие ( и закрытие ) является синтаксисом для обозначения того, что эта вынкция выполняется немедленно.

Такие функции используются для предотвращения загрязнения глобального пространства имен в среде исполнения JavaScript. Первая строка исходного кода Backbone.js имеет IIFE, которая оборачивает остальной код, изолируя объявленные переменые внутри библиотеки до того как они станут доступны глобально. Это делается для того, чтобы предотвратить ситуацию, когда переменная используется несколько раз в глобальном пространстве имен на веб-странице.

Например, объявленные в самом начале исходного кода Backbone.js переменные потенциально могут быть изменены в другом месте на странице, если их не поместить внутри IIFE:

 Наследование

При разработке приложения на Backbone.js вашы представления быдут выглядеть примерно так:

MyView расширяет базовый Backbone.View, это означает, что она наследует свойства и методы Backbone.View. Как пользователь Backbone.js можно также переопределить эти унаследованные совайства и методы в своей реализации.

Существует три различных вида свойств и методов, которые содержит вазовый класс Backbone:

Свойства/методы, которые, как ожидается, будут переопределены

Backbone.View явно говорит, что initialize и render должны быть переопределны, так как их реализация пуста:

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

Свойства/методы, которые могут быть перееопределны опционально

Методы Backbone.Model и sync Backbone.Collection являются лучшим примером методов, которые работают без пользовательской реализации, но могут быть переопределены необходимым функционалом:

В реализации sync по-умолчанию выше, модель или коллекция просто вызывает метод Backbone.sync с аргументами, которые были получены в контексте объекта. Подробнее об этом ниже.

На практике вы можете реализовать localStorage в моделях/коллекциях для устранения ненужных сетевых запросов. Чтобы добиться этого, можно переопределить метод sync как в следующей модели:

Я проверяю, если ключ MyData хранится в localStorage и он существует, то читаю его оттуда. Если нет, то я вызываю Backbone.sync также как это реализовано по-умолчанию. Эта особенность Backbone действительно мощная, так как позволяет определить уровень индивидуальности ваших классов.

Менее распространенный метод переопределения

Метод sync явно сообщает пользователю, что он может быть переопредлен пользовательской функцией, но вы также можете переопределить многие другие методы Backbone. В документации представлен следующий пример для переопределения метода Backbone.Model.set:

Это похоже на подход, который мы видели выше, за исключением того что, что мы вызываем метод set в Backbone.Model вместо копирования его функциональности. Обратите внимание на .prototype добавленного после класса, который наследует метод Backbone.Model.

Такой подход имеет смыл, если нам необходимо выполнить некоторую логику до обновления модели  стандартным методом set Backbone.Model.

Свойства/методы, которые не должны переопределяться или вызываться

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

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

Это присутствует по всему исходному коду Backbone.js и вот пример приватных методов в классе Backbone.View:

Эти приватные методы вызываются внутри класса Backbone.View и выступают в качестве поддержки публичных методов или конструктора класса. Например, метод _.configure() вызывается в конструкторе Backbone.View для настройки представления на основе аргумента options переданного пользователем.

JavaScript конструкторы

После написания собственных Backbone представлений, вы будете их вызывать примерно следующим образом:

Ключевое слово new создает новый экземпляр MyView путем вызова его конструктора и возвращения объекта, содержащего наследуемые свойства и методы. Скорее всего при программировании с Backbone вы не будете определять пользовательский конструктор, так как унаследованный конструктор обеспечит ожидаемую логику для подготовки класса. Вот конструктор Backbone.View:

Этот конструктор настроит представление на получение уникального id, определит настройки из аргумента options, обеспечит связь представления с элементом, а затем инициализирует представление и делегирует события DOM.

Ключевое слово this

Понимание this имеет важное значение для продвинутого программирования на JavaScript. Это относится к объекту, в котором текущая функция была вызвана. В представлении Backbone, когда вы пишите this.render() внутри вашей функции initialize, this откносится к вашему представлению, потому что применяется в функции конструктора выше.

Одно из интересных использований this в Backbone.View находится в методе delegateEvents. Следующий код из этого метода связывает обработчик событий jQuery в соответствующем представлении, так что this относится к MyView вместо DOM элемента, который получил событие:

underscore.js

Это мощьная утилита, которая позволяет писать более наглядный код. При работе с массивами или объектами вы можете использовать такие методы как _.first, _.any и _.without, а не писать свои собственные функции для работы с данными. Backbone предоставляет методы underscore непосредственно в Backbone.Collection и Backbone.Model для удобного доступа к методам.

В дополнение к вышеописанным методам, underscore реализует кросс-браузерные версии самых новых JavaScript функций, которые доступны только в совеременных браузерах. underscore определеяет поддерживает ли браузер метод и использует его нативно, если это возможно.

Выводы

Я надеюсь, что этот пост будет полезен для разработчиков, которые хотят развивать знания о JavaScript и Backbone.js! Я рекомендую исследовать освещенные концепции, написав фрагменты кода в консоле веб-браузера или конмандной строке node.js. Пишите в комментарии, если у вас есть какие-либо вопросы.

Оригинальный пост на английском языке