Частые ошибки

В данной главе мы рассмотрим некоторые наиболее частые ошибки начинающих программистов на JavaScript.

Случайное использование оператора присваивания

Программы на JavaScript могут генерировать неожиданные результаты, если программист случайно в выражении if использовал оператор присваивания (=) вместо оператора сравнения (==).

Следующее выражение if возвращает false (как и ожидалось), потому что x не равно 10:


var x = 0;
if (x == 10) 

Следующее выражение if возвращает true (возможно, не как и ожидалось), потому что 10 — это true:


var x = 0;
if (x = 10) 

Следующее выражение if возвращает false (возможно, не как и ожидалось), потому что 0 — это false:


var x = 0;
if (x = 0) 

Внимание! Присваивание всегда возвращает присвоенное значение.

Ожидание свободного сравнения

При обычном сравнении тип данных не имеет значения. Следующее выражение if возвращает true:


var x = 10;
var y = "10";
if (x == y) 

При строгом сравнении тип данных учитывается. Следующее выражение if возвращает false:


var x = 10;
var y = "10";
if (x === y) 

Частой ошибкой бывает то, что программист забывает, что выражение switch использует строгое сравнение.

Следующее выражение switch выведет окно предупреждения:


var x = 10;
switch(x) {
    case 10: alert("Привет");
 } 

Следующее выражение switch ничего не выведет:


var x = 10;
switch(x) {
    case "10": alert("Привет");
 } 

Путаница с конкатенацией и сложением

Конкатенация — это складывание строк.

Сложение — это складывание чисел.

В JavaScript обе эти операции используют один и тот же оператор (+).

Из-за этого складывание числа с числом и числа со строкой дают разные результаты:


var x = 10 + 5;          // результат 15
var x = 10 + "5";        // результат "105" 

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


var x = 10;
var y = 5;
var z = x + y;           // в z будет 15

var x = 10;
var y = "5";
var z = x + y;           // в z будет "105" 

Недопонимание чисел с плавающей точкой

Все числа в JavaScript хранятся в виде 64-битных чисел с плавающей точкой (тип Float).

У всех языков программирования, включая JavaScript, возникают трудности с точностью операций со значениями с плавающей точкой:


var x = 0.1;
var y = 0.2;
var z = x + y            // в z не будет 0.3

Решить эту проблему поможет умножение и деление:


var x = 0.1;
var y = 0.2;
var z = (x * 10 + y * 10) / 10;       // в z будет 0.3

Перенос строки JavaScript

JavaScript допускает перенос выражения на другую строку:


var x =
"Привет, мир!";

Однако, перенос выражения посередине строки работать не будет:


var x = "Привет,
мир!";

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


var x = "Hello \
World!"; 

Ошибки с расстановкой точки с запятой

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


if (x == 19);
{
     // блок кода
} 

Прерывание выражения return

В соответствии с поведением JavaScript по умолчанию в конце строки выражение автоматически закрывается.

Благодаря этому следующие два примера дадут один и тот же результат.

Пример 1


function myFunction(a) {
    var power = 10  
    return a * power
}

Пример 2


function myFunction(a) {
    var power = 10;
    return a * power;
}

При этом JavaScript допускает перенос выражения на другую строку.

Из-за этого пример 3 даст тот же результат, что и примеры 1 и 2.

Пример 3


function myFunction(a) {
    var
    power = 10;  
    return a * power;
} 

Но что будет, если разбить на две строки выражение return, как в следующем примере.

Пример 4


function myFunction(a) {
    var
    power = 10;  
    return
    a * power;
} 

Функция вернет значение undefined!

Почему? Потому что JavaScript думает, что вы подразумевали следующее:


function myFunction(a) {
    var
    power = 10;  
    return;
    a * power;
} 

Это объясняется так:

Если выражение не закончено, как:


var 

JavaScript попытается закончить его, прочитав следующую строчку:


power = 10; 

Но так как это выражение закончено:


return 

JavaScript автоматически закроет его:


return; 

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

JavaScript закроет в конце строки выражение return, потому что это законченное выражение.

Никогда не разрывайте выражение return!

Обращение к элементам массива по именам

Многие языки программирования поддерживают массивы с индексами-именами.

Массивы с индексами-именами называются ассоциативными массивами.

JavaScript не поддерживает ассоциативные массивы.

В JavaScript массивы используют числовую индексацию:


 var person = [];
 person[0] = "John";
 person[1] = "Doe";
 person[2] = 46;
 var x = person.length;         // person.length вернет 3
 var y = person[0];             // person[0] вернет значение "John" 

В JavaScript именованную индексацию используют объекты.

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

После автоматического переопределения методы и свойства массива будут возвращать некорректные значения или значение undefined:


 var person = [];
 person["firstName"] = "John";
 person["lastName"] = "Doe";
 person["age"] = 46;
 var x = person.length;         // person.length вернет 0
 var y = person[0];             // person[0] вернет значение undefined 

Завершающая запятая в определениях

Согласно спецификации ECMAScript 5 допускается использовать запятую в конце определения объектов и массивов.

Пример объекта:


 person = {firstName:"John", lastName:"Doe", age:46,} 

Пример массива:


 points = [40, 100, 1, 5, 25, 10,]; 

ВНИМАНИЕ !! Internet Explorer 8 в этом случае аварийно закончит свою работу. JSON не допускает использование запятой в конце определения объектов и массивов.

JSON:


 person = {firstName:"John", lastName:"Doe", age:46} 
 points = [40, 100, 1, 5, 25, 10]; 

Undefined не Null

В JavaScript значение null для объектов, значение undefined для переменных, свойств и методов.

Чтобы получить значение null, объект должен быть определен, иначе у него будет значение undefined.

Если вы хотите проверить существует ли объект, то следующее выражение приведет к ошибке, если объект имеет значение undefined:


if (myObj !== null && typeof myObj !== "undefined")  

Чтобы все было корректно, сначала вы должны провести проверку на typeof():


if (typeof myObj !== "undefined" && myObj !== null)  

Ожидание области видимости у блока кода

JavaScript не создает отдельную область видимости для каждого блока кода.

Хотя это верно для некоторых языков программирования, в JavaScript это не так.

Следующий код будет отображать значение переменной i (10), даже ЗА ПРЕДЕЛАМИ блока цикла:


for (var i = 0; i < 10; i++) {
    // какой-то код
 }
return i;