Reg.ru: домены и хостинг

Крупнейший регистратор и хостинг-провайдер в России.

Более 2 миллионов доменных имен на обслуживании.

Продвижение, почта для домена, решения для бизнеса.

Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

Перейти на сайт->

Бесплатный Курс "Практика HTML5 и CSS3"

Освойте бесплатно пошаговый видеокурс

по основам адаптивной верстки

на HTML5 и CSS3 с полного нуля.

Начать->

Фреймворк Bootstrap: быстрая адаптивная вёрстка

Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.

Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.

Верстайте на заказ и получайте деньги.

Получить в подарок->

Бесплатный курс "Сайт на WordPress"

Хотите освоить CMS WordPress?

Получите уроки по дизайну и верстке сайта на WordPress.

Научитесь работать с темами и нарезать макет.

Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!

Получить в подарок->

*Наведите курсор мыши для приостановки прокрутки.


11 ошибок при работе с JavaScript

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

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


Ошибка № 1 - Вы используете глобальные переменные

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

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

В действительности, нет.

Эта идея плоха тем, что вы можете непреднамеренно переписать содержимое ваших переменных.

Хостинг

Скажем, у вас есть интернет-магазин, и вы используете JavaScript для того, чтобы отображать цены всех товаров в корзине с покупками (разумеется, вы все это пересчитываете на стороне сервера; JavaScript же используется как декоративная примочка). Ваш код в этом случае может выглядеть примерно так:


var total = 0, // общая цена
tax = 0.05; // налог 5%

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


var total = 15; // количество отображаемых твитов

или


var tax = function () { /* ... */ }; // функция Trigger Animation eXperience (tax)

Теперь у вас неприятности: две важные переменные были перезаписаны, а вы даже можете не догадываться об этом.

Ваш код теперь будет работать с неверными данными, а вы рискуете потратить кучу времени и нервов, пока обнаружите ошибку и устраните ее.

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


(function () {
    var total = 0, tax = 0.05;
    // дальнейший код
}());

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

Такой код работает для "домашнего" использования, но не очень подходит, если вы работаете профессионально или собираетесь распространять ваш код.

К примеру, если вы хотите создать покупательскую корзину, которую могли бы использовать другие, было бы здорово использовать модульный подход:


var cartTotaler = (function () {
    var total = 0; tax = 0.05;
    
    // дальнейший код

    return {
      addItem : function (item) { },
      removeItem : function (item) { },
      calculateTitle : function () { }
    };
}());

И еще один момент по глобальным переменным: если вы не используете ключевое слово var при создании переменной, то JavaScript в этом случае по умолчанию создаст глобальную переменную:


(function () {
  tax = 0.05;
}());

var totalPrice = 100 + (100 * tax); // 105

Переменная tax доступна за пределами функции потому что объявлена без использования ключевого слова var. Будьте внимательны!


Ошибка № 2 - Вы не используете точку с запятой (;)

Каждая команда в JavaScript должна завершаться точкой с запятой. Очень просто. Если вы не поставите точку с запятой, то за вас это сделает компилятор.

Отсюда вопрос: зачем нам тратить время, если компилятор все равно сделает все за нас?

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

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

Мое же мнение такое: всякий раз, когда вы полагаетесь на то, что компилятор JavaScript подкорректирует ваш код (пусть даже самую малость), вы подвергаете риску работоспособность своего скрипта.

Давайте посмотрим на простую функцию:


function returnPerson (name) {
    return
    {
        name : name
    };
}

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

Решением будет такой подход:


return {
    name : name
};

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

Вполне логично также, что вы, будучи веб-разработчиком, работаете и с другими языками (к примеру, с PHP), в которых точку с запятой ставить нужно обязательно. Так есть ли смысл "переключаться" с одного на другое, если можно писать код единообразно на разных языках?


Ошибка № 3 - Вы используете ==

Встаньте прямо сейчас из-за монитора и прогуляйтесь, пока не встретите первого попавшегося JavaScript-разработчика. Попросите его/ее назвать вам одну типичную ошибку при работе с JavaScript и он/она скажет: "Использование двойного знака равенства вместо тройного".

Что это означает?

Испробуйте такой код:


if (1 == 1) {
    console.log("Это верно!");
}

Работает именно так, как вы и ожидали, верно? Теперь попробуйте следующее:


if (1 == '1') {
    console.log("Это верно!");
}

Да, вы снова получаете слова Это верно! в консоли... и да, это плохо.

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

Решение - использовать тройное равенство ===. Оно не производит преобразования типов там, где не просят, поэтому и значение, и тип остаются именно такими, какими вы ожидаете их увидеть.

Хостинг

Очевидно, все то же самое применимо и к операторам != и !==.

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


''         == '0' // false
'0'        == ''  // true
false      == '0' // true
' \t\r\n ' == 0   // true 


Ошибка № 4 - Вы используете "объектные обертки"

JavaScript любезно (хм?) предоставляет нам возможность использовать "объектные обертки" для простого (хм?) создания примитивных типов:


new Number(10);
new String("hello");
new Boolean(true);
new Object();
new Array("one", "two", "three");

Прежде всего, это просто супер неудобно. Все эти вещи можно сделать куда меньшим количеством кода:


10;
"hello";
true;
{};
["one", "two", "three"];

Однако, постойте! Это не одно и то же.

Это значит, что если проверить тип для Number(10) или String("hello") с помощью typeof, то мы получим object - не то, что ожидаем. К тому же, использование "объектных оберток" может привести к неожиданному поведению программы, отличному от ее поведения при работе с примитивными значениями.

Так зачем же в JavaScript существуют такие объекты? Это связано с тем, что они используются для внутренних целей.

Примитивные значения в действительности не имеют методов (т.к. не являются объектами). Поэтому, когда вы вызываете метод примитивного объекта (вроде "hello".replace("ello", "i")), JavaScript создает "объектную обертку" для строки, делает то, что вам нужно, после чего удаляет объект.

Оставьте "объектные обертки" для JavaScript и пользуйтесь примитивными значениями.

Примечание: возможно, это лишнее, но я хочу донести до новичков следующее: я не говорю, что вам не следует использовать функцию-конструктор и ключевое слово new (хотя некоторые рекомендуют именно это). Этот совет применим к примитивным типам данных: числам, строкам; к массивам и пустым объектам.


Ошибка № 5 - Вы не проверяете свойства при использовании for-in

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

Если вы делали это ранее, то использовали цикл for-in:


var prop, obj = { name: "Иван", job: "Веб-разработчик", age: 25 };

for (var prop in obj) {
  console.log(prop + ": " + obj[prop]);
}

Если вы выполните код выше, то получите такой вывод:


name: Иван  
job: Веб-разработчик  
age: 25

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

Поэтому, чтобы отфильтровать свойства, не относящиеся к текущему объекту, вам следует использовать метод hasOwnProperties:


Function Dog (name) {
    this.name = name;
}
Dog.prototype.legs = 4;
Dog.prototype.speak = function () {
    return "Гав!";
};

var d = new Dog("Шарик");

for (var prop in d) {
    console.log( prop + ": " + d[prop] );
}

console.log("=====");

for (var prop in d) {
  if (d.hasOwnProperty(prop)) {
    console.log( prop + ": " + d[prop] );
  }
}

// Результаты

// name: Шарик
// legs: 4
// speak: function () {
        return "Гав!";
// }
// =====
// name: Шарик

Иногда у вас может также возникнуть необходимость просмотреть все свойства, но отфильтровать все методы. Это можно сделать, используя метод typeof:


for (var prop in d) {
  if (typeof d[prop] !== 'function') {
    console.log( prop + ": " + d[prop] );
  }
}

В любом случае, будьте внимательны при использовании for-in, чтобы избежать нежелательных результатов.


Ошибка № 6 - Вы используете with или eval

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

Давайте начнем с with. Две главные причины не использовать данную конструкцию:

- это действительно сильно замедляет работу вашего скрипта;
- не всегда очевидно, что вы делаете.

Первый пункт пояснений не требует, поэтому переходим ко второму.

Вкратце, как это работает: вы передаете объект оператору with, затем внутри блока with вы можете получать доступ к свойствам объекта как к переменным:


var person = { name: "Иван", age : 25 };

with (person) {
  console.log(name); // Иван
  console.log(age);  // 25
}

Но что же произойдет, ели у нас есть переменная с таким же именем, как и свойство объекта, к которому мы применяем with?

В общем случае, если существуют переменная и свойство с одним и тем же именем, будет использоваться переменная.

Другой момент заключается в том, что вы не можете добавить свойство к объекту внутри конструкции with. Как можно видеть из примера ниже, заданное для свойства job значение остается пустым при обращении через объект, однако сама переменная существует и хранит значение Дизайнер.


var person = { name: "Иван", age : 25 },
    name = "Андрей";

with (person) {
  console.log(name); // Андрей
  job = "Дизайнер";
} 

console.log(person.job); // undefined;
console.log(job); // Дизайнер

А что же насчет eval?

Если в целом, то вы можете передать строку кода этой функции, и она его выполнит.


eval( "Console.log('hello!');" );

Звучит безобидно, скорее даже радует своими возможностями, верно? В этом-то и заключается основная проблема: это слишком мощная штука.

В действительности нет никаких причин использовать эту функцию т.к.:

- вы можете просто написать непосредственно код;
- eval замедляет работу скрипта, как и with.

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

Вы действительно хотите дать посетителям вашего сайта полный контроль над своим кодом? Надеюсь, что нет.

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


Ошибка № 7 - Вы игнорируете основание системы счисления при использовании функции parseInt

В JavaScript есть хорошая удобная функция parseInt, которая позволяет конвертировать строку, содержащую число в значение числового типа.


parseInt("200"); // 200
parseInt("043"); // 35

Хм, что же тут произошло? Разве во второй строке должно быть не 43?

В действительности parseInt работает не только с десятичной системой счисления, поэтому, когда функция "видит" строку, начинающуюся с нуля, то она считает, что имеет дело с числом в восьмеричной системе счисления.

Вот почему нужно передавать данной функции второй параметр - необходимую систему счисления:


parseInt("020", 10); // 20
parseInt("100", 2);  // 4


Ошибка № 8 - Вы не используете фигурные скобки при работе с if и while

Одна из очевидных привлекательных сторон JavaScript - его гибкость. Однако иногда это может сыграть с вами злую шутку.

Речь идет о фигурных скобках для конструкций if и while. Они необязательны, если у вас в блоке кода только одна строка:


if (true)
  console.log("Внутри условия if");
 

Это здорово, потому что вы можете даже разместить все необходимое в одну строку:


var arr = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"],
    i   = arr.length - i;

while (i) console.log( arr[i--] );

Но это не очень здорово по двум причинам: первая - это может выглядеть неочевидно:


if (true) 
  console.log("Внутри условия if");
  console.log("Вне условия if");

Видите, о чем я? Вторая строка не входит в условие if, однако выглядит все так, словно она к нему относится. Скобки, разумеется, прояснят ситуацию.

Также, если вам вдруг понадобится добавить дополнительные строки, то вам нужно помнить о том, что нужно добавить еще и фигурные скобки. Гораздо проще озадачиться этим с самого начала. Так сделайте это.


Ошибка № 9 - Вы добавляете элементы в DOM поштучно

Ок, ок, это не совсем JavaScript, но в 99 случаях из 100 использование JavaScript подразумевает работу с DOM (Document Object Model - Объектная Модель Документа).

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


var list = document.getElementById("list"),
    items = ["one", "two", "three", "four"],
    el;

for (var i = 0; items[i]; i++) {
  el = document.createElement("li");
  el.appendChild( document.createTextNode(items[i]) );
  list.appendChild(el); // Медленно, плохая идея
}

Вот что следует сделать вместо этого: используйте фрагменты документа.

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

Фрагмент документа - это не узел, и для него нет соответствующего визуального отражения в DOM. Это просто невидимый контейнер для ряда DOM-элементов, который используется как промежуточный этап перед реальной модификацией DOM. Итак, как можно поступить:


var list = document.getElementById("list"),
    frag = document.createDocumentFragment(),
    items = ["one", "two", "three", "four"],
    el;

for (var i = 0; items[i]; i++) {
  el = document.createElement("li");
  el.appendChild( document.createTextNode(items[i]) );
  frag.appendChild(el); // Лучше!
}

list.appendChild(frag);

Быстрее, четче, понятнее - почему не полюбить?)


Ошибка № 10 - Вы не изучаете JavaScript

JavaScript не равняется jQuery. Я вас удивил?

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

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

Не будьте одним из таких людей: вокруг множество добротных уроков и руководств, поэтому не ищите себе оправдания. Если все, что вы знаете - это jQuery (или Mootools, или еще что-нибудь), то вы ставите себя в неудобное положение.


Ошибка № 11 - Вы следуете всем правилам

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

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

Но правда в том, что если вы понимаете, почему не рекомендуется делать то-то и то-то, это знание становится вашим помощником и вы учитесь использовать правильные инструменты в правильной ситуации.

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

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

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

По материалам http://net.tutsplus.com
Перевод: Дмитрий Науменко

P.S. Присмотритесь к премиум-урокам по различным аспектам сайтостроения, включая JavaScript, jQuery и Ajax, а также к бесплатному курсу по созданию своей CMS-системы на PHP с нуля. Все это поможет вам быстрее и проще освоить практические навыки веб-программирования:

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!


Смотрите также:

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

CodeIgniter: жив или мертв?

CodeIgniter: жив или мертв?

Функции обратного вызова, анонимные функции и механизм замыканий

Функции обратного вызова, анонимные функции и механизм замыканий

Применение функции к каждому элементу массива

Применение функции к каждому элементу массива

Слияние массивов. Преобразование массива в строку

Слияние массивов. Преобразование массива в строку

Деструктор и копирование объектов с помощью метода __clone()

Деструктор и копирование объектов с помощью метода __clone()

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

PHP: Удаление элементов массива

PHP: Удаление элементов массива

Ключевое слово final (завершенные классы и методы в PHP)

Ключевое слово final (завершенные классы и методы в PHP)

50 классных сервисов, программ и сайтов для веб-разработчиков

50 классных сервисов, программ и сайтов для веб-разработчиков

Наверх