7 пунктов JavaScript, которые облегчат жизнь новичкам

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

Короткая запись

Одна из чудесных особенностей JavaScript - это короткая запись при объявлении объектов и массивов. Так, если нужно создать объект, то можно написать:

var car = new Object();
car.colour = 'red';
car.wheels = 4;
car.hubcaps = 'spinning';
car.age = 4;

Но тоже самое можно сделать и так:

var car = {
  colour:'red',
  wheels:4,
  hubcaps:'spinning',
  age:4
}

Получается короче и не нужно повторять имя объекта. В примере  car очень короткое имя, а если вы используете invalidUserInSession? Нужно помнить о ляпе такой записи в IE. Никогда не оставляйте замыкающей запятой перед закрывающейся фигурной скобкой, иначе у вас возникнут проблемы.

Для массивов тоже есть короткая запись. Так, приверженцы старой школы могут объявлять массив следующим образом:

var moviesThatNeedBetterWriters = new Array(
  'Transformers','Transformers2','Avatar','Indiana Jones 4'
);

Но есть более короткий вариант:

var moviesThatNeedBetterWriters = [
  'Transformers','Transformers2','Avatar','Indiana Jones 4'
];

Другой момент, который касается массивов, заключается в том, что нет такой сущности, как ассоциативный массив. Можно найти множество примеров, в которых выше приведенный объект car определялся бы следующим образом:

var car = new Array();
car['colour'] = 'red';
car['wheels'] = 4;
car['hubcaps'] = 'spinning';
car['age'] = 4;

"Ассоциативный массив" - это  путающее название для объекта.

Еще одна короткая запись используется для условий. Так вместо следующего кода:

var direction;
if(x < 200){
  direction = 1;
} else {
  direction = -1;
}

Можно написать:

var direction = x < 200 ? 1 : -1;

В случае, если условие будет иметь значение true, выполнится то, что стоит после знака вопроса, а в другом случае выполнится то, что стоит после двоеточия.

JSON как формат данных

До того как был разработан JSON для хранения данных, разработчики использовали (а некоторые продолжают) различные чудные методы для хранения контента в формате, готовом для JavaScript: массивы, строки с управляющими символами для разделения и другие чудачества. Создание Дугласом Крокфордом JSON изменило все. Используя JSON вы можете хранить сложные данные в формате, которые является естественным для JavaScript и при этом не нужно проводить дополнительные конверсии.

JSON - это сокращение от "JavaScript Object Notation"(запись объектов JavaScript). В ней используются все описанные выше сокращения.

Например, сделать описание рок группы можно так:

var band = {
  "name":"The Red Hot Chili Peppers",
  "members":[
    {
      "name":"Anthony Kiedis",
      "role":"lead vocals"
    },
    {
      "name":"Michael 'Flea' Balzary",
      "role":"bass guitar, trumpet, backing vocals"
    },
    {
      "name":"Chad Smith",
      "role":"drums,percussion"
    },
    {
      "name":"John Frusciante",
      "role":"Lead Guitar"
    }
  ],
  "year":"2009"
}

Вы можете использовать JSON непосредственно в JavaScript и, когда оборачивается в вызов функции, даже в качестве возвращаемого формата API. Такой метод называется JSON-P и поддерживается множеством API. Вы можете использовать точку данных, в которую непосредственно возвращается JSON-P в скрипте:

<div id="delicious"></div><script>
function delicious(o){
  var out = '<ul>';
  for(var i=0;i<o.length;i++){
    out += '<li><a href="' + o[i].u + '">' +
           o[i].d + '</a></li>';
  }
  out += '</ul>';
  document.getElementById('delicious').innerHTML = out;
}
</script>
<script src="http://feeds.delicious.com/v2/json/codepo8/javascript?count=15&callback=delicious"></script>

В данном примере вызывается сервис Delicious Web для получения закладок по теме JavaScript в формате JSON, а затем они выводятся в виде неупорядоченного списка.

По существу, JSON является вероятно самым легким способом описания сложных данных — и он работает в браузерах. Его можно использовать даже в PHP с помощью функции json_decode().

Встроенные функции JavaScript

Для многих становится открытием, что математические и строчные функции JаvaScript могут существенно облегчить жизнь. Их можно использовать для  исключения циклов и условий. Например, поиск самого большого числа в массиве чисел может быть написан с использованием цикла:

var numbers = [3,342,23,22,124];
var max = 0;
for(var i=0;i<numbers.length;i++){
  if(numbers[i] > max){
    max = numbers[i];
  }
}
alert(max);

А можно добиться того же без использования цикла:

var numbers = [3,342,23,22,124];
numbers.sort(function(a,b){return b - a});
alert(numbers[0]);
Заметьте, что функция sort() сортирует массив лексически, поэтому для числового массива нужно использовать возвратную функцию, чтобы получить правильный порядок чисел.

Другой интересный метод - Math.max(). Он возвращает наибольшее число из списка параметров:

Math.max(12,123,3,2,433,4); // Возвращает 433

Так как метод проверяет числовые значения и возвращает наибольший среди них, то его можно использовать для определения поддержки браузером различных свойств:

var scrollTop= Math.max(
 doc.documentElement.scrollTop,
 doc.body.scrollTop
);

Это пример решения проблемы с Internet Explorer. Вы можете прочитать scrollTop для текущего документа, но в зависимости от DOCTYPE документа то или другое свойство получит значение. При использовании Math.max() вы получаете правильное значение, так как другое будет undefined.

Другие мощные функции предназначены для манипуляции строками - split() и join(). Вероятно, что самым лучшим примером будет присоединение класса  CSS к элементу.

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

Итак, оригинальная функция будет такой:

function addclass(elm,newclass){
  var c = elm.className;
  elm.className = (c === '') ? newclass : c+' '+newclass;
}

Можно автоматизировать операцию с помощью методов split() и join():

function addclass(elm,newclass){
  var classes = elm.className.split(' ');
  classes.push(newclass);
  elm.className = classes.join(' ');
}

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

Делегирование событий

События выполняют работу веб приложения. Они позволяют расширять функционал без затрагивания кода ядра приложения. Основной проблемой является то, что события могут пропадать: вы используете перехватчик события для определенного элемента, он становится активным, но ничего не происходит. Приходится принимать данный факт, что браузеры (такие как  IE6) имеют разного рода проблемы при работе с памятью и в них используется слишком много различных событий. Поэтому мудрым решением будет не использовать много обработчиков событий в документе.

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

Что это значит? Допустим у вас есть список ссылок, и нужно вызывать функцию, когда загружается ссылка. Код HTML такой:

<h2>Great Web resources</h2>
<ul id="resources">
<li><a href="http://opera.com/wsc">Opera Web Standards Curriculum</a></li>
<li><a href="http://sitepoint.com">Sitepoint</a></li>
<li><a href="http://alistapart.com">A List Apart</a></li>
<li><a href="http://yuiblog.com">YUI Blog</a></li>
<li><a href="http://blameitonthevoices.com">Blame it on the voices</a></li>
<li><a href="http://oddlyspecific.com">Oddly specific</a></li>
</ul>

Обычно для применения обработчиков событий используется цикл по всем ссылкам:

// Пример классической обработки событий
(function(){
  var resources = document.getElementById('resources');
  var links = resources.getElementsByTagName('a');
  var all = links.length;
  for(var i=0;i<all;i++){
    // Присоединяем обработчик к каждой ссылке
    links[i].addEventListener('click',handler,false);
  };
  function handler(e){
    var x = e.target; // Получаем ссылку, на которой произошло событие
    alert(x);
    e.preventDefault();
  };
})();

Но то же самое можно сделать одним обработчиком события:

(function(){
  var resources = document.getElementById('resources');
  resources.addEventListener('click',handler,false);
  function handler(e){
    var x = e.target; // Получаем ссылку, на которой произошло событие
    if(x.nodeName.toLowerCase() === 'a'){
      alert('Event delegation:' + x);
      e.preventDefault();
    }
  };
})();

Так как событие происходит на всех элементах списка, все что вам нужно - это сравнить nodeName с тем элементом, который реагирует на событие.

Ограничения: оба выше приведенных примера предназначены для работы в браузерах  и они закончатся ошибкой в IE6. Для IE6 нужно использовать модель событий, отличную от W3C. Поэтому для трюков используются библиотеки.

Выгода от такого подхода больше, чем просто использование одного обработчика событий. Допустим, вы хотите динамически добавить ссылок в список. С делегированием событий вам не нужно ничего менять. В случае простой обработки событий придется переназначать обработчики событий и повторно проходить циклом список.

Анонимные функции и шаблоны модулей

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

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

var name = 'Chris';
var age = '34';
var status = 'single';
function createMember(){
  // [...]
}
function getMemberDetails(){
  // [...]
}

Любой другой скрипт на странице, который имеет переменную с именем status, может стать источником проблем. Если обернуть все определенные функции и переменные  именем, например, myApplication, то подобные коллизии будут исключены:

var myApplication = function(){
  var name = 'Chris';
  var age = '34';
  var status = 'single';
  function createMember(){
    // [...]
  }
  function getMemberDetails(){
    // [...]
  }
}();

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

(function(){
  var name = 'Chris';
  var age = '34';
  var status = 'single';
  function createMember(){
    // [...]
  }
  function getMemberDetails(){
    // [...]
  }
})();

Если нужно, чтобы переменные и функции были доступны снаружи, то нужно немного изменить их объявление. Чтобы createMember() или getMemberDetails() были доступны снаружи, нужно вернуть их, чтобы сделать их свойствами myApplication:

var myApplication = function(){
  var name = 'Chris';
  var age = '34';
  var status = 'single';
  return{
    createMember:function(){
      // [...]
    },
    getMemberDetails:function(){
      // [...]
    }
  }
}();
// myApplication.createMember() и
// myApplication.getMemberDetails() теперь доступны.

Это называется шаблоном модуля. Такой метод широко используется в библиотеке Yahoo UI. Использование другого синтаксиса для обеспечения доступа к переменным и функциям из внешнего мира может напрягать. К тому же приходится использовать предшествующее название модуля ( в нашем примере  myApplication). Можно несколько укоротить запись с помощью возврата указателей на элементы, которые надо сделать публичными. Таким образом можно использовать более короткие имена:

var myApplication = function(){
  var name = 'Chris';
  var age = '34';
  var status = 'single';
  function createMember(){
    // [...]
  }
  function getMemberDetails(){
    // [...]
  }
  return{
    create:createMember,
    get:getMemberDetails
  }
}();
//myApplication.get() и myApplication.create() теперь можно использовать.

Обеспечение возможности конфигурации

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

Чтобы избежать такой ситуации вы можете добавить объект конфигурации к своим скриптам. Вот основная сущность данного действия:

  • Сделайте объект, который будет являться частью скрипта, и назовите его configuration.
  • В нем надо хранить все, что другие любят менять, когда они используют чужие скрипты:
    • CSS ID и имена классов;
    • Строки (такие как метки) для генерируемых кнопок;
    • Значения, например, "количество отображаемых изображений," "размер карты";
    • Различные локальные установки.
  • Объект должен иметь свойство public, чтобы другие могли его изменить.

Почти все выше описанное выполняется на завершающем этапе кодирования.

В действительности вы даете другим возможность использовать ваш код и легко изменять его под свои нужды.

Интерактивность для фоновой обработки данных

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

Конечно, можно получить JSON-P от веб сервиса в качестве ответа на запрос и сделать конверсию данных на стороне клиента. Но зачем заниматься этим если есть сервер, который располагает значительно большими возможностями для конвертации данных и последующего возврата их как JSON или HTML, да еще к тому же и может кэшировать их для загрузки?

Если вы планируете использовать AJAX, изучайте HTTP и создание собственных кэширующих и конверсионных прокси. Таким образом вы сэкономите много времени и нервов в ходе разработки проекта.

Специальный код для браузера - зря потраченное время. Используйте библиотеки!

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

Конечно, опыт по написанию кода всегда остается с вами, но может стоит заниматься более продуктивными вещами, которые оставляют после себя след в истории?

Библиотеки, например, YUI, jQuery и Dojo, помогают разработчикам создавать кросс-браузерные приложения. Они берут на себя проблемы браузеров: плохую реализацию функций, несоответствие стандартам, ошибки в коде. Кроме того, библиотеки  помогают избавиться от рутинных операций.

Если вы не занимаетесь бета тестированием браузера, так как являетесь большим его фанатом, то не стоит делать специфические вставки кода для него. Будет очень обидно, когда их придется удалять.

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

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: www.smashingmagazine.com/2010/04/20/seven-javascript-things-i-wish-i-knew-much-earlier-in-my-career/
Перевел: Сергей Фастунов
Урок создан: 31 Августа 2010
Просмотров: 31016
Правила перепечатки


5 последних уроков рубрики "Разное"

или авторизуйтесь, чтобы добавлять комментарии, оценивать уроки и сохранять их в личном кабинете
  • 31 Августа 2010 21:36
    AronTito
    Неплохо
  • 31 Августа 2010 22:47
    НеБот
    Неплохо :)
  • 1 Сентября 2010 07:58
    Zubik
    Неплохо
  • 2 Сентября 2010 00:45
    rubyx
    Всё нужно знать!
^ Наверх ^