Роботландский Университет © А.А.Дуванов |
Урок знакомит читателя с базовыми элементами языка:
Переменная это именованная область памяти для хранения данных. Данные могут быть разных типов: целое число, десятичная дробь, логическая константа, текстовая строка. В компилируемых языках (таких, как Си, Паскаль) перед использованием переменной она обязательно описывается (либо явно программистом, либо по умолчанию транслятором). Ведь данные каждого типа по-своему кодируются двоичными нулями и единицами в памяти компьютера, и обработка каждого типа происходит по своим алгоритмам.
В интерпретируемом языке JavaScript нет описателей типов данных (таких, как int, float, char в Си). Переменная описывается ключевым словом var, которое не вносит никакой типизации. Описатель var просто фиксирует именованную область для хранения данных, не приписывая этой области никакого типа. Это не означает, конечно, что JavaScript одинаково работает с любыми данными. Это означает лишь, что тип переменной определяется по типу присваиваемого значения и может много раз меняться в процессе работы программы:
var x; // Описана переменная // (фиксируется область для хранения данных). x = 10; // Сейчас переменная хранит целое число 10. x = "10"; // Сейчас переменная хранит строку "10". x = 30+10; // Сейчас переменная хранит число 40. x = 30+"10"; // Сейчас переменная хранит строку "3010". x = 30-"10"; // Сейчас переменная хранит целое число 20. x = "30"-10; // Сейчас переменная хранит целое число 20. x = "30"-"10"; // Сейчас переменная хранит целое число 20.
Заметьте, что в выражении 30+"10" число 30 преобразуется в строку, а операция + рассматривается как операция конкатенации (соединение двух строк).
В выражении 30-"10" строка "10" преобразуется в число 10, после чего выполняется вычитание. Аналогично в выражении "30"-10 строка "30" преобразуется в число.
Видно, что браузер производит преобразование типов данных по контексту, и иногда не совсем так, как ожидает программист. Нужно быть очень внимательным, и не следует полагаться на автоматическое преобразование типов при выполнении реальных программ.
Там, где нет полной уверенности, лучше пользоваться явным преобразованием при помощи встроенных в язык функций parseInt и parseFloat (урок 5):
var y = "30"; x = parseInt(y,10)-10;
Несмотря на то, что JavaScript позволяет описывать переменные в любом месте, и даже не описывать их вовсе, описания нужно делать обязательно и собирать их в одном месте (в начале функции, скрипта). Если переменная не описана программистом явно, браузер описывает ее (заводит под нее область памяти) самостоятельно при первом упоминании. При этом переменная считается глобальной.
Глобальная переменная доступна в любой части кода текущего HTML-файла. А это очень плохо. Легко случайно испортить ее значение.
Примите на вооружение полезное правило: переменные нужно описывать всегда.
Если действительно нужна глобальная переменная, опишите ее явно в
первом блоке
Цепочка из нескольких блоков
Переменные, описанные вне функций, видны всюду. Такие описания считаются глобальными.
Выбор имени очень важен. Вот несколько советов.
Из приведенных правил 2 и 3 есть очевидные исключения:
i, j | | счетчики циклов |
col | | индекс столбца |
row | | индекс строки |
cur | | текущее значение |
max | | максимум (обычно в качестве префикса или суффикса: maxCol) |
min | | минимум (обычно в качестве префикса или суффикса: ValueMin) |
s, str | | строка (если нельзя ее назвать более содержательно) |
buf | | буфер (временное хранилище) |
len | | длина (обычно как префикс или суффикс: lenStr) |
ret | | возвращаемое из функции значение |
sum | | сумма |
Из правил 1 и 4 исключений быть не может!
Достаточно сложно уследить за всеми ключевыми словами языка и легко попасть в ловушку.
Однажды Сидоров назвал функцию, обрабатывающую щелчок на кнопке Старт, очень подходящим именем start, и в браузерах четвертых версий все работало прекрасно. После появления Microsoft Internet Explorer 5 на Сидорова посыпались рекламации: гипертекстовое приложение не работало. Причина оказалась именно в имени start, которое в IE-5 стало ключевым словом.
С тех пор Сидоров принял для себя правило: добавлять к нормальным именам один и тот же предохранительный суффикс. Он переименовал start в startRU, pointer в pointerRU и все стало прекрасно работать.
Мера, конечно, нужна во всем. Но я за понятные программы в ущерб некоторой эффективности. Как именовать Горбункова Семена Семеновича?
Есть два способа:
Представьте, что мы оставили бы от Семена Семеновича одну аббревиатуру гсс никто бы Горбункова и не признал. С трудом бы узнали его и за шифром ГорСеСе. Какой способ именования из a) и b) вам больше по душе? Выбирайте! Но старайтесь придерживаться одной нотации на протяжении всей программы, а лучше всего программирования.
Это вариант уродлив и избыточен:
var ret = "ok!"; if(...хорошо...) return ret;
Лучше записать так:
if(...хорошо...) return true;
Константы в программах нельзя оставлять без имен.
При суммировании всех элементов массива set лучше всего воспользоваться свойством set.length, указывающим длину массива:
// Суммирование всех элементов массива. // set.length - свойство массива: его длина. var sum = 0; for(var i=0; i<set.length; i++) sum += set[i];
Суммирование первой сотни элементов можно задать так:
var bonus = new Array(....); // Массив оценок. var important_length = 100; // Число важных оценок (они идут первыми). var middle_important_bonus; // Средняя оценка среди важных. // Суммирование важных оценок. middle_important_bonus = 0; for(var i=0; i<important_length; i++) middle_important_bonus += bonus[i]; // Нахождение средней оценки среди важных. middle_important_bonus /= important_length;
Что это дает?
Если программа почему-то работает с первыми 100 числами массива, то, вероятно, в этом есть сермяжная правда. И это число 100 будет встречаться в программе много раз (у нас уже два раза).
Если через месяц важными окажутся не 100 элементов, а 200, придется кропотливо перечитывать уже забытый код, чтобы всюду заменить 100 на 200. Много шансов, что некоторые замены не будут выполнены (там, например, где стоит 99, которое означает important_length-1), а некоторые будут выполнены неправильно (например, число 100, означающее проценты, заменится на 200).
Таких неприятностей легко можно избежать, если именовать константы замена будет производиться только в одном месте, да и читать такую программу будет гораздо легче.
Магических чисел в программе быть не должно, но 0 и 1 очевидные исключения.
В этом суммировании массива:
var sum = 0; for(var i=0; i<set.length; i++) sum += set[i];
И в этом нахождении произведения:
var num = 10; var factorial = 1; for(var i=1; i<=num; i++) factorial *= i;
константы 0 и 1 в самом деле, числа магические! Именовать их не надо!
Существует практика именования переменных русскими словами, записанными латинскими буквами. С одной стороны, в этом нет ничего плохого:
// Возвращает НОД чисел a и b. function Nod(a,b) { ..... } var summa = 0; // Сумма элементов массива. var dlina = 10; // Длина актуальной части массива. var poz; // Текущая позиция в строке.
Однако, в таком виде удается написать гораздо меньше красивых и понятных имен, чем на английском языке. Сравните:
var counter; // Счетчик чего-то... var schetchik; // Счетчик чего-то... var bonus; // Оценка за урок. var ozenka; // Оценка за урок. function number_of_elements() // Число элементов. function chislo_elementov() // Число элементов. function error_message() // Сообщение об ошибке. function soobchenie_ob_osibke() // Сообщение об ошибке.
Совет такой: на этапе написания кода держите под рукой маленький русско-английский словарь и пользуйтесь им при выборе подходящего имени. Заодно потихоньку пойдет обучение словам, которые все равно нужно знать по-английски тем, кто занимается программированием и компьютерами.
И еще: хорошей практикой является комментирование имен при их описании.
Конечно, не надо комментировать переменную цикла! Описание остальных имен надо помещать в одном месте (в начале) и сопровождать максимально подробными комментариями.
Описание функции нужно также предварять подробными комментариями, в которых обязательно указывать:
Пример:
// Вычисление НОД(а,b). // Вход: a и b - натуральные числа. // Выход: НОД(а,b) или 0, если a и b не являются допустимыми. function Nod(a,b) { ... }
Но даже несмотря на комментарии, для выбора содержательных, понятных и красивых имен не надо жалеть времени. Ведь, если одна переменная называется kfrm, а другая krfm, то читать программу практически невозможно, даже если эти переменные подробным образом откомментированы в начале скрипта.
Команда присваивания имеет вид:
Рассмотрим сложный пример из задания 2g зачетного класса урока:
var x = 13; var y = 3; y = x++%y++;
Работает это так:
Теперь переменная x имеет значение 14, а переменная y значение 1.
Сюрприз для тех, кто пишет на Паскале.
Оказывается, в Си и вслед за ним в JavaScript, команда присваивания
Если мы пишем:
x = 1; y = x+1;
то можно и не думать о второй ипостаси команды. Но эти две
команды можно кодировать как одну:
Работает это так:
А что, если опустить скобки:
y = x = 1 + 1;
Что произойдет теперь?
Правильный ответ дает второй вариант, то есть x и y получат значения 2.
Из таблицы приоритетов операций JavaScript (смотрите справочный раздел в конце книги) следует:
Это означает, что в последнем примере:
Команды:
переменная += выражение; переменная -= выражение; переменная *= выражение; переменная /= выражение; переменная %= выражение;
тоже имеют статус операции. Значение этой операции совпадает со значением, которое получает переменная.
В следующем примере:
var x=1; var y; y = (x+=2)+1;
переменная y получит значение 4, а переменная x значение 3.
Наиболее популярно использования операции = в цепочке присваиваний:
x = y = z = t = выражение;
Здесь нескольким переменным присваивается одно и тоже значение.
Можно увидеть и такие записи:
Подумайте, что они означают!
А вот настоящее безумие:
y = ++(x=1);
К счастью, оно не работает (браузер выдает сообщение об ошибке). Операции ++ и -- применимы только к переменным, но не к выражениям.
![]() |