Область действия относится к тому, где доступны переменные и функции и в каком контексте они выполняются.

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

JavaScript имеет два типа областей видимости: глобальную и локальную. Глобально объявленные переменные, доступные в глобальной области видимости. Переменные, объявленные внутри функций, доступны только внутри этой функции и являются локальными переменными.

## Глобальные переменные

Любая переменная, объявленная глобально, или любые переменные, объявленные вне функции, называются глобальными переменными. Он доступен из любого места в коде.

var globalVariable = ‘globally’;
function foo(){
 // the global variable accessible inside a function
 console.log(globalVariable); // globally
}

### нет переменной

Если переменные определены без `var` вне функций, они являются глобальной переменной. Переменная без `var` внутри функции будет искать цепочку областей видимости, пока не найдет переменную или не попадет в глобальную область видимости и не создаст ее.

// a variable declared globally
var globalVariable = ‘globally’;
// a variable without var belongs to global scope
withoutVar = ‘globally, not declared globally’;
function foo() {
 // a variable not declared so belgongs to its global scope
 withoutVarInsideFunction = “globally, not declared inside function”;
 console.log(‘Inside function:’);
 console.log(globalVariable);
 console.log(withoutVar);
 console.log(withoutVarInsideFunction);
}
foo();
console.log(‘Outside function:’);
console.log(globalVariable);
console.log(withoutVar);
console.log(withoutVarInsideFunction);

## Локальные переменные

Локальная переменная — это когда она только что определена и доступна в функции.

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

function foo() {
 // local scope
 var localVariable = ‘local’;
}
// global scope
console.log(localVariable); // Uncaught ReferenceError: localVariable is not defined
// catch clause-scoped variable
var globalVariable = ‘globally’;
try {
 throw ‘inside of try’
} catch (globalVariable) {
 console.log(globalVariable); // inside of try
}
console.log(globalVariable); // globally

### Затенение переменных

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

Одна и та же переменная может быть указана на нескольких уровнях вложенной области, что называется «затенением». Внутренняя переменная затеняет внешнюю переменную. Независимо от затенения поиск области всегда начинается с самой внутренней области, выполняемой в данный момент, и продвигается наружу до первого совпадения и останавливается. Локальная переменная имеет более высокий приоритет, чем переменная из внешней области.

// global scope
var globalVariable = ‘globally’;
function shadow() {
 // local scope
 var globalVariable = ‘local scope’;
 console.log(globalVariable); // local scope
}
shadow(); // local scope
// global scope
var globalVariable = ‘globally’;
function shadow(globalVariable) {
 // local scope
 console.log(globalVariable); // undefined
}
shadow(); // undefined
// global scope
var globalVariable = ‘globally’;
function shadowInIf() {
 if (true) {
 var globalVariable = ‘local scope’
 }
console.log(globalVariable); // local scope
}
var globalVariable = ‘globally’;
var foo = (function () {
 var globalVariable = ‘inside function’;
 return function () {
 // closure
 console.log(globalVariable); // inside function
 }
})();
foo(); // inside function

# Объявление функции

Объявление функции определяет именованную функциональную переменную, не требуя назначения переменной.

function foo() {
 // code…
}

# Функциональные выражения

Функциональное выражение определяет функцию как часть более крупного синтаксиса выражения. Определенные функции Функции Выражения могут быть именованными или анонимными.

// anonymous function expression
var a = function() {
 // code…
}
// named function expression
var f = function foo() {
 // code…
}
f(); // call the function
// function name cannot access outeside
foo(); // Uncaught ReferenceError
// self invoking funciton expression
// IIFE (immediately invoked function expression)
(function bar() {
 // code…
})();

# Подъем

«Объявления функций и функциональные переменные всегда перемещаются («поднимаются») интерпретатором JavaScript наверх своей области видимости».

a = ‘declared at end, assignment at top’
console.log(a); // declared at end, assignment at top
var a;

эквивалентный поднятый код будет выглядеть так:

var a;
a = ‘declared at end, assignment at top’;
console.log(a); // declared at end, assignment at top

Объявление переменной поднимается, а присвоение переменной — нет.
JavaScript поднимает только объявление.

console.log(a); // undefined
var a = ‘declaration and assignment at end’;

эквивалентный поднятый код будет выглядеть так:

var a;
console.log(a); // undefined
a = ‘declaration and assignment at end’;

Объявление функции поднимается.

foo(); // inside function
function foo() {
 console.log(‘inside function’);
}

эквивалентный поднятый код будет выглядеть так:

function foo() {
 console.log(‘inside function’);
}
foo (); // inside function

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

var firstLine;
function firstLine() {
 console.log(‘inside function’)
}
console.log(firstLine); // firstLine is a function
// ƒ firstLine() {
// console.log(‘inside function’)
// }

эквивалентный поднятый код будет выглядеть так:

function firstLine() {
 console.log(‘inside function’)
}
var firstLine;
console.log(firstLine); // firstLine is a function
// ƒ firstLine() {
// console.log(‘inside function’)
// }

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

var firstLine = ‘first line’;
function firstLine() {
 console.log(‘inside function’)
}
console.log(firstLine); // first line
// firstLine is a variable

эквивалентный поднятый код будет выглядеть так:

function firstLine() {
 console.log(‘inside function’)
}
var firstLine;
firstLine = ‘first line’;
console.log(firstLine); // first line

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

Объявление переменной поднимается, но их выражения присваивания — нет.

foo(); // Uncaught TypeError: foo is not a function
var foo = function () {
 console.log(‘inside function’);
}

эквивалентный поднятый код будет выглядеть так:

var foo;
foo(); // Uncaught TypeError: foo is not a function
foo = function () {
 console.log(‘inside function’);
}

Функции, назначенные переменным, не поднимаются.