Андрей Кулешов




JavaScript
Хороший тон клиентской разработки
JavaScript
Самый популярный и самый ненавидимый язык
программирования в мире


▪ Первая инкарнация – под именем LiveScript (в девичестве Mocha)
▪ Переименован в JavaScript как знак союза двух корпораций
  Этим переименованием были введены в заблуждение, и вводяся до сих пор,
  многие и многие программисты
▪ Стандартизован под именем ECMAScript
▪ Синтаксисом напоминает Си-подобные языки и Java, чем и вызывает
  большую часть ненависти в свой адрес, так как ведет себя иногда
  совершенно по иному.
Где используется ECMAScript?
▪ Браузеры – клиентская часть веб-сайтов.
▪ NodeJS – серверная часть веб-сайтов
▪ Action Script (Flash, Flex)
▪ Шеллы для Windows/Linux
▪ Внедрение в собственные продукты для предоставления пользователям
  возможностей программирования
▪ И даже попытки программировать микроконтроллеры
JavaScript как кривое зеркало Си-языков
▪ JavaScript особенно неприятен людям, которые долго и успешно писали на
  Си-подобных языках
▪ Тут похожие циклы, похожие фигурные скобочки, чуть-чуть похожее
  объявление фукций и переменных...
▪ И совсем другие области видимости и правила работы с необъявленными
  переменными
Проверка и присвоение значений
Си-подобные                                    JavaScript

▪ if (item != null)                            ▪ if (item)
▪ if (str != null && str.length > 0)           ▪ if (str)
▪ if (val != 0) { x = val; } else { x = 5; }   ▪ x = val || 5;
▪ if (item != null) { x = item.text; }         ▪ x = item && item.text;
=== и его злобный брат-близнец ==
▪ Все приходящие с Си-языков пишут:      Выражение           Результат
  if(a == b) {
     …                                   5 == “5”            True
  }
  Оно даже как будто бы работает         0 == null           False
▪ Но очень смешно – пытаясь              undefined == null   True
  приводить типы и сравнивать            „0‟ == „‟           False
  результат.
                                         0 == „0‟            True
▪ Лучше использовать пару === / !==,
  которая не использует приведение       0 == „‟             True
  типов
                                         ' trn ' == 0     True
▪ Тогда ни у кого из читателей кода не   false == „0‟        True
  возникнет вопрос, является ли
  ошибкой равенство 0 == false, или
  это ваш хитрый приѐм
  программирования
Объявление переменных
▪ То, что нужно помнить всегда – областью видимости переменной является
  функция
▪ Причем вся функция, а не только та часть функции, которая ниже
  объявления переменной
Подъем переменых (variables hoisting)
Что пишем мы                   Как это читает JavaScript

function f() {                 function f() {
  var greeting = ‘hello’;        var greeting = ‘hello’,
  for(var i = 0; i < 4; i++)         i = undefined,
  {                                  spaced = undefined;
    var spaces = ‘ ‘ + ‘ ‘;      for(i = 0; i < 4; i++)
    greeting += spaces;          {
  }                                spaces = ‘ ‘ + ‘ ‘;
}                                  greeting += spaces;
                                 }
                               }
Простое правило – пишите так, как это
прочитает JavaScript
▪ Все переменные, используемые в функции, всегда объявляйте на самом еѐ
  верху
▪ Во всей функции должен быть только один оператор var – на первой позиции
▪ Так вы сможете гарантировать отсутствие недопониманий со стороны менее
  опытных разработчиков
▪ И – да, это коренным образом расходится с советом из Си – объявляйте
  переменную по месту еѐ использования
  И поначалу вызывает оторопь.
В сложных функциях появляются огромные
секции объявления переменных
function f() {
var i,
    j,
    k,
    greeting = 'hello',
    total = 0,
    name = "GetDev.NET",
    message = greeting + " " + name,
    st,
    containerId = '#container‘,
    minX,
    maxX,
    minY,
    maxY,
    tempResult,
…..


Что служит неплохим сигналом к рефакторингу
Не засоряйте глобальный объект
▪ Каждая ваша новая переменная, созданная вне функции, добавляется к
  глобальному объекту. Туда же (в обычном режиме) добавляют и
  переменные, которые забыли объявить.
▪ С каждой новой переменной увеличивается риск совпадения имен – как
  между вашими собственными переменными, так и между добавленными
  сторонней библиотекой или плагином браузера/среды выполнения
▪ (Кстати, если вы используете переменную без объявления, причем в любом
  месте, то она, обычно, попадает как раз в глобальный объект. Исключение –
  “strict mode”)
Namespaces
▪ Вообще-то их в JavaScript нет, но, условно говоря, они есть
▪ В качестве namespace используется обычный объект – в идеале – один
  корневой объект на приложение
▪ Все остальные переменные являются его свойствами
var GetDevNet = GetDevNet || {};
GetDevNet.map = new Map();
GetDevNet.url = ‚http://getdev.net/‛

▪ Смысле этого ровно тот же: логическая группировка объектов, функций и
  переменных (теперь – свойств)
Самовызывающиеся функции
▪ Самовызывающаяся функция – функция, которая исполняется немедленно
  после объявления
▪ Смысле еѐ – спрятать внутри себя логику, переменные и данные
(function (GD, $, global) {
    GD.title = $(‚#title‛).text();
})(GetDevNet, jQuery, window);
Замыкания
▪ Хранение ссылок на объекты/значения из более высокого скопа
  function getItemsCounter() {
    var count = 0;
    return {
      getItemsCount: function () {
        return count;
      },
      addItem: function () {
        count++;
      }
    };
  }
▪ Позволяет иметь приватные данные – счетчик здесь
Классы…
▪ Типичные стадии изучения JavaScript:
  - узнаем язык программирования
  - узнаем, что в JS есть классы!
  - узнаем, что в объектах классов нет приватных свойств
  - узнаем, что в JS нет классов. Есть функции-конструкторы
  - узнаем, что в функциях-конструкторах можно организовать приватные
  свойства

 Но это тема отдельная и довольно глубокая.
Модули
▪ Задача модуля – инкапсуляция независимого куска логики
▪ var GetDevModule = (function ($, global) {
    //some initialization…
    …
    var module = {
      …
      …
    } ;
    return module;
  })(jQuery, window);
▪ (function (GetDev, $, global) {
    GetDev.module = {
      …
      …
    };
  })(GetDev, jQuery, window);
Используйте Strict Mode
▪ “strict mode”;
▪ Старые браузеры эту строку проигнорируют, а новые переключатся на
  использование строгого режима – подмножества разрешенных операций
  JavaScript
▪ Тут вы уже не сможете случайно объявить глобальную переменную, что
  плюс уже само по себе
Юнит-тестировние
▪ Юнит-тестирование – это хорошо в принципе
  Но для JavaScript это хорошо особенно
▪ В отличие от компилируемых языков, в которых проверка синтаксиса всего кода
  выполняется естественным образом во время компиляции, об ошибке
  синтаксиса JavaScript мы узнаем только во время выполнения
▪ Автоматически запускаемые юнит-тесты помогают значительно приблизить во
  времени момент выявления ошибки
▪ Вместо цикла «написал - откомпилировал – узнал об ошибке» получаем цикл
  «написал – залился – запустились тесты на Continous Integration-сервере –
  узнал об ошибке».
  Что несколько дольше во времени, но все равно быстрее и надежнее, чем
  «написал – выложил – получил сообщение от пользователей «что-то не
  работает»»
Существующие фреймворки
▪ QUnit – от автором jQuery, написанный для тестирования jQuery
  Просто нормальный фреймворк
  Набор ассертов, setup/teardown, визуальный интерфейс как HTML-страница
  Выполняется внутри браузера (просто открываем HTML-файл с тестами)
  Отсутствует возможность запуска на сервере вне браузера
▪ JUnit JS – тот же шарик, вид сбоку
  assertEqual-операции принимают аргументы в порядке, обратном QUnit, так
  что заменить в процессе один на другой будет более проблематично
▪ Jasmine – Behavior Driven Development фреймворк
  Из плюсов – улучшенная поддержка Mock- и Spy-объектов из коробки
▪ PhantomJS – среда для запуска JavaScript-тестов без браузера
Организация Continous Integration
▪ Первый подход – запускать на сервере браузер и прогонять в нѐм тесты


▪ Второй подход – запускать на сервере тесты в невизуальной среде
  (PhantomJS, V8)


▪ Оба подхода имеют преимущества и недостатки
Демо – создание страницы с тестами
Интересное чтение
▪ JavaScript: the Good Parts by Douglas Crockford
▪ http://javascript.ru
▪ StackOverflow – unit testing discussion
Интересное видео
▪ The Tale of JavaScript. I Mean ECMAScript. by Douglas Crockford
▪ Good JavaScript Habits for C# Developers by Elijah Manor
▪ Structuring JavaScript Code – Pluralsight
▪ Crockford on JavaScript video series on Yahoo!
Интересные ссылки
▪ JSLint - средство поиска очевидных ошибок и проверка следованию
  хорошему стилю программирования
  http://www.jslint.com/
▪ JS Fiddle – средство исполнения кода, разметки и CSS-стилей в онлайне
  http://jsfiddle.net/
▪ QUnit
  http://qunit.org
▪ PhantomJS
  http://phantomjs.org/
Вопросы?
                 Внимательно слушаю! 


Андрей Кулешов

kaa-tula@ya.ru
    akuleshov.tula




Специально для http://GetDev.NET