В данной главе мы рассмотрим некоторые наиболее частые ошибки начинающих программистов на 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;