var flat = function(size) {
for (var count = 0; count < size; count++)
result += "_";
};
var mountain = function(size) {
result += "/";
for (var count = 0; count < size; count++)
result += "'";
result += "\\";
};
flat(3);
mountain(4);
flat(6);
mountain(1);
flat(1);
return result;
};
console.log(landscape());
// → ___/''''\______/'\_
Функции flat
и mountain
видят переменную result
, потому что они находятся внутри функции, в которой она определена. Но они не могут видеть переменные count
друг друга, потому что переменные одной функции находятся вне области видимости другой. А окружение снаружи функции landscape
не видит ни одной из переменных, определённых внутри этой функции.
Короче говоря, в каждой локальной области видимости можно увидеть все области, которые её содержат. Набор переменных, доступных внутри функции, определяется местом, где эта функция описана в программе. Все переменные из блоков, окружающих определение функции, видны – включая и те, что определены на верхнем уровне в основной программе. Этот подход к областям видимости называется лексическим.
Люди, изучавшие другие языки программирования, могут подумать, что любой блок, заключённый в фигурные скобки, создаёт своё локальное окружение. Но в JavaScript область видимости создают только функции. Вы можете использовать отдельно стоящие блоки:
var something = 1;
{
var something = 2;
// Делаем что-либо с переменной something...
}
// Вышли из блока...
Но something
внутри блока – это та же переменная, что и снаружи. Хотя такие блоки и разрешены, имеет смысл использовать их только для команды if
и циклов.
Если это кажется вам странным – так кажется не только вам. В версии JavaScript 1.7 появилось ключевое слово let
, которое работает как var
, но создаёт переменные, локальные для любого данного блока, а не только для функции.
Имена функций обычно используют как имя для кусочка программы. Такая переменная однажды задаётся и не меняется. Так что легко перепутать функцию и её имя.
Но это – две разные вещи. Вызов функции можно использовать, как простую переменную – например, использовать их в любых выражениях. Возможно хранить вызов функции в новой переменной, передавать её как параметр другой функции, и так далее. Также переменная, хранящая вызов функции, остаётся обычной переменной и её значение можно поменять:
var launchMissiles = function(value) {
missileSystem.launch("пли!");
};
if (safeMode)
launchMissiles = function(value) {/* отбой */};
В главе 5 мы обсудим чудесные вещи, которые возможно сделать, передавая вызовы функций другим функциям.
Есть более короткая версия выражения “var square = function…”
. Ключевое слово function можно использовать в начале инструкции:
function square(x) {
return x * x;
}
Это объявление функции. Инструкция определяет переменную square и присваивает ей заданную функцию. Пока всё ок. Есть только один подводный камень в таком определении.
console.log("The future says:", future());
function future() {
return "We STILL have no flying cars.";
}
Такой код работает, хотя функция объявляется ниже того кода, который её использует. Это происходит оттого, что объявления функций не являются частью обычного исполнения программ сверху вниз. Они «перемещаются» наверх их области видимости и могут быть вызваны в любом коде в этой области. Иногда это удобно, потому что вы можете писать код в таком порядке, который выглядит наиболее осмысленно, не беспокоясь по поводу необходимости определять все функции выше того места, где они используются.
А что будет, если мы поместим объявление функции внутрь условного блока или цикла? Не надо так делать. Исторически разные платформы для запуска JavaScript обрабатывали такие случаи по разному, а текущий стандарт языка запрещает так делать. Если вы хотите, чтобы ваши программы работали последовательно, используйте объявления функций только внутри других функций или основной программы.
function example() {
function a() {} // Нормуль
if (something) {
function b() {} // Ай-яй-яй!
}
}
Полезным будет присмотреться к тому, как порядок выполнения работает с функциями. Вот простая программа с несколькими вызовами функций:
function greet(who) {
Читать дальше