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




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

JavaScript: хороший тон клиентской разработки

  • 1.
    Андрей Кулешов JavaScript Хороший тонклиентской разработки
  • 2.
    JavaScript Самый популярный исамый ненавидимый язык программирования в мире ▪ Первая инкарнация – под именем LiveScript (в девичестве Mocha) ▪ Переименован в JavaScript как знак союза двух корпораций Этим переименованием были введены в заблуждение, и вводяся до сих пор, многие и многие программисты ▪ Стандартизован под именем ECMAScript ▪ Синтаксисом напоминает Си-подобные языки и Java, чем и вызывает большую часть ненависти в свой адрес, так как ведет себя иногда совершенно по иному.
  • 3.
    Где используется ECMAScript? ▪Браузеры – клиентская часть веб-сайтов. ▪ NodeJS – серверная часть веб-сайтов ▪ Action Script (Flash, Flex) ▪ Шеллы для Windows/Linux ▪ Внедрение в собственные продукты для предоставления пользователям возможностей программирования ▪ И даже попытки программировать микроконтроллеры
  • 4.
    JavaScript как кривоезеркало Си-языков ▪ JavaScript особенно неприятен людям, которые долго и успешно писали на Си-подобных языках ▪ Тут похожие циклы, похожие фигурные скобочки, чуть-чуть похожее объявление фукций и переменных... ▪ И совсем другие области видимости и правила работы с необъявленными переменными
  • 5.
    Проверка и присвоениезначений Си-подобные 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;
  • 6.
    === и егозлобный брат-близнец == ▪ Все приходящие с Си-языков пишут: Выражение Результат 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, или это ваш хитрый приѐм программирования
  • 7.
    Объявление переменных ▪ То,что нужно помнить всегда – областью видимости переменной является функция ▪ Причем вся функция, а не только та часть функции, которая ниже объявления переменной
  • 8.
    Подъем переменых (variableshoisting) Что пишем мы Как это читает 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; } }
  • 9.
    Простое правило –пишите так, как это прочитает JavaScript ▪ Все переменные, используемые в функции, всегда объявляйте на самом еѐ верху ▪ Во всей функции должен быть только один оператор var – на первой позиции ▪ Так вы сможете гарантировать отсутствие недопониманий со стороны менее опытных разработчиков ▪ И – да, это коренным образом расходится с советом из Си – объявляйте переменную по месту еѐ использования И поначалу вызывает оторопь.
  • 10.
    В сложных функцияхпоявляются огромные секции объявления переменных function f() { var i, j, k, greeting = 'hello', total = 0, name = "GetDev.NET", message = greeting + " " + name, st, containerId = '#container‘, minX, maxX, minY, maxY, tempResult, ….. Что служит неплохим сигналом к рефакторингу
  • 11.
    Не засоряйте глобальныйобъект ▪ Каждая ваша новая переменная, созданная вне функции, добавляется к глобальному объекту. Туда же (в обычном режиме) добавляют и переменные, которые забыли объявить. ▪ С каждой новой переменной увеличивается риск совпадения имен – как между вашими собственными переменными, так и между добавленными сторонней библиотекой или плагином браузера/среды выполнения ▪ (Кстати, если вы используете переменную без объявления, причем в любом месте, то она, обычно, попадает как раз в глобальный объект. Исключение – “strict mode”)
  • 12.
    Namespaces ▪ Вообще-то ихв JavaScript нет, но, условно говоря, они есть ▪ В качестве namespace используется обычный объект – в идеале – один корневой объект на приложение ▪ Все остальные переменные являются его свойствами var GetDevNet = GetDevNet || {}; GetDevNet.map = new Map(); GetDevNet.url = ‚http://getdev.net/‛ ▪ Смысле этого ровно тот же: логическая группировка объектов, функций и переменных (теперь – свойств)
  • 13.
    Самовызывающиеся функции ▪ Самовызывающаясяфункция – функция, которая исполняется немедленно после объявления ▪ Смысле еѐ – спрятать внутри себя логику, переменные и данные (function (GD, $, global) { GD.title = $(‚#title‛).text(); })(GetDevNet, jQuery, window);
  • 14.
    Замыкания ▪ Хранение ссылокна объекты/значения из более высокого скопа function getItemsCounter() { var count = 0; return { getItemsCount: function () { return count; }, addItem: function () { count++; } }; } ▪ Позволяет иметь приватные данные – счетчик здесь
  • 15.
    Классы… ▪ Типичные стадииизучения JavaScript: - узнаем язык программирования - узнаем, что в JS есть классы! - узнаем, что в объектах классов нет приватных свойств - узнаем, что в JS нет классов. Есть функции-конструкторы - узнаем, что в функциях-конструкторах можно организовать приватные свойства Но это тема отдельная и довольно глубокая.
  • 16.
    Модули ▪ Задача модуля– инкапсуляция независимого куска логики ▪ var GetDevModule = (function ($, global) { //some initialization… … var module = { … … } ; return module; })(jQuery, window); ▪ (function (GetDev, $, global) { GetDev.module = { … … }; })(GetDev, jQuery, window);
  • 17.
    Используйте Strict Mode ▪“strict mode”; ▪ Старые браузеры эту строку проигнорируют, а новые переключатся на использование строгого режима – подмножества разрешенных операций JavaScript ▪ Тут вы уже не сможете случайно объявить глобальную переменную, что плюс уже само по себе
  • 18.
    Юнит-тестировние ▪ Юнит-тестирование –это хорошо в принципе Но для JavaScript это хорошо особенно ▪ В отличие от компилируемых языков, в которых проверка синтаксиса всего кода выполняется естественным образом во время компиляции, об ошибке синтаксиса JavaScript мы узнаем только во время выполнения ▪ Автоматически запускаемые юнит-тесты помогают значительно приблизить во времени момент выявления ошибки ▪ Вместо цикла «написал - откомпилировал – узнал об ошибке» получаем цикл «написал – залился – запустились тесты на Continous Integration-сервере – узнал об ошибке». Что несколько дольше во времени, но все равно быстрее и надежнее, чем «написал – выложил – получил сообщение от пользователей «что-то не работает»»
  • 19.
    Существующие фреймворки ▪ QUnit– от автором jQuery, написанный для тестирования jQuery Просто нормальный фреймворк Набор ассертов, setup/teardown, визуальный интерфейс как HTML-страница Выполняется внутри браузера (просто открываем HTML-файл с тестами) Отсутствует возможность запуска на сервере вне браузера ▪ JUnit JS – тот же шарик, вид сбоку assertEqual-операции принимают аргументы в порядке, обратном QUnit, так что заменить в процессе один на другой будет более проблематично ▪ Jasmine – Behavior Driven Development фреймворк Из плюсов – улучшенная поддержка Mock- и Spy-объектов из коробки ▪ PhantomJS – среда для запуска JavaScript-тестов без браузера
  • 20.
    Организация Continous Integration ▪Первый подход – запускать на сервере браузер и прогонять в нѐм тесты ▪ Второй подход – запускать на сервере тесты в невизуальной среде (PhantomJS, V8) ▪ Оба подхода имеют преимущества и недостатки
  • 21.
    Демо – созданиестраницы с тестами
  • 22.
    Интересное чтение ▪ JavaScript:the Good Parts by Douglas Crockford ▪ http://javascript.ru ▪ StackOverflow – unit testing discussion
  • 23.
    Интересное видео ▪ TheTale 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!
  • 24.
    Интересные ссылки ▪ JSLint- средство поиска очевидных ошибок и проверка следованию хорошему стилю программирования http://www.jslint.com/ ▪ JS Fiddle – средство исполнения кода, разметки и CSS-стилей в онлайне http://jsfiddle.net/ ▪ QUnit http://qunit.org ▪ PhantomJS http://phantomjs.org/
  • 25.
    Вопросы? Внимательно слушаю!  Андрей Кулешов kaa-tula@ya.ru akuleshov.tula Специально для http://GetDev.NET