Полный цикл в digital

Область видимости переменных

Все переменные и константы в JavaScript имеют определенную область видимости, в пределах которой они могут действовать.

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

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

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>hmarketing.ru</title>
</head>
<body>
<script>
var a = 5;
let b = 8;
const c = 9;
function displaySum(){
var d = a + b + c;
console.log(d);
}
// 22
displaySum(); 
</script>
</body>

Здесь переменные a и b и константа c являются глобальными. Они доступны из любого места программы, переменная d глобальной не является, так как она определена внутри функции и видна только в этой функции.

Определение локальной области видимости

Для определения локальной области видимости в JavaScript используются фигурные скобки { }, которые создают блок кода. Этот блок кода может быть безымянным, может быть именнованным, например, функция, может представлять условную или циклическую конструкцию. Например, определение переменных в безымянном блоке кода:

{
var a = 5;
let b = 8;
const c = 9;
}

Однако в этом случае поведение переменной зависит от способа ее определения (через var или через let) и от типа блока, var определяет локальные переменные уровня функции, а let определяет локальные переменные уровня блока кода (подобным образом const определяет константы уровня блока кода).

Переменные и константы функции

Переменные и константы, определенные внутри функции, видны (то есть могут использоваться) только внутри этой функции:

function print(){
var a = 5;
let b = 8;
const c = 9;
console.log("Function print: a =", a);
console.log("Function print: b =", b);
console.log("Function print: c =", c);
}
print();
// Uncaught ReferenceError: a is not defined
console.log("Global: a =", a);

Переменные a и b и константа c являются локальными, они существуют только в пределах функции. Вне функции их нельзя использовать, поэтому мы получим следующий консольный вывод:

Function print: a= 5
Function print: b= 8
Function print: c= 9
Uncaught ReferenceError: a is not defined

Локальные переменные в блоках кода, условиях и циклах

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

Переменная, объявленная с помощью var, может использоваться вне блока:

// безымянный блок
{
var a = 5;
}
// a = 5
console.log("a =", a);  
// условная конструкция
if(true){
var b = 6;
}
// b = 6
console.log("b =", b);  
// цикл
for(var i = 0; i < 5; i++){
var c = 7;
}
// c = 7
console.log("c =", c);

Единственное условие, что блок кода должен срабатывать, чтобы инициализировать переменную. Так, в примере выше условие в конструкции if и в цикле for установлено так, что блок этих конструкций будет выполняться. Однако, что если условие будет иным, и блок не будет выполняться? В таком случае мы опять же сможем обращаться к переменным, только они будут иметь значение undefined:

if(false){
var b = 6;
}
// b = undefined
console.log("b =", b);  
// цикл
for(var i = 1; i < 0; i++){
var c = 7;
}
// c = undefined
console.log("c =", c);

Теперь посмотрим, как будут вести себя в подобной ситуации переменные, определенные с помощью let:

{
let a = 5;
}
// Uncaught ReferenceError: a is not defined
console.log("a =", a);

В данном случае мы получим ошибку. Мы можем использовать переменные let, определенные внутри блока кода, только внутри этого блока кода. Тоже самое относится и к константам:

{
const b = 5;
}
// Uncaught ReferenceError: b is not defined
console.log("b =", b);

Скрытие переменных

Что если у нас есть две переменных - одна глобальная, а другая локальная, которые имеют одинаковое имя:

var z = 89;
function print(){
var z = 10;
// 10
console.log(z); 
}
// 10
print();

В этом случае в функции будет использоваться та переменная z, которая определена непосредственно в функции. То есть локальная переменная скроет глобальную. Однако конкретное поведение при сокрытии зависит от того, как определяется переменная.

Выше было указано, что var определяет переменную уровня функции. Поэтому с помощью оператора var мы не можем определить одновременно две переменных с одним и тем же именем и в функции, и в блоке кода в этой функции. Если мы это сделаем, то при объявлении переменной на уровне блока мы меняем значение переменной уровня функции:

function displayZ(){
var z = 20;
{
// Не определяет новую переменную, а изменяет значение переменной z уровня функции
var z = 30; 
console.log("Block:", z);
}
console.log("Function:", z);
}
displayZ();

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

Block: 30
Function: 30

Как писалось выше, оператор let определяет переменную уровня блока кода. То есть каждый блок кода определяет новую область видимости, в которой существует переменная. Ве блока кода, где определена переменная, она не существует. Соответственно мы можем одновременно определить переменную на уровне блока и на уровне функции (в отличие от var):

let z = 10;
function displayZ(){
let z = 20;
{
let z = 30;
console.log("Block:", z);
}
console.log("Function:", z);
}
displayZ();
console.log("Global:", z);

Здесь внутри функции displayZ определен блок кода, в котором определена переменная z (вместо безымянного блока это мог быть и блок условной конструкции или цикла). Она скрывает глобальную переменную и переменную z, определенную на уровне функции, в данном случае мы получим следующий консольный вывод:

Block: 30
Function: 20
Global: 10

Все, что относится к оператору let, относится и к оператору const, который определяет константы уровня блока кода. Блоки кода задают область видимости констант, а константы, определенные на вложенных блоках кода, скрывают внешние константы с тем же именем:

const z = 10;
function displayZ(){
const z = 20;
{
const z = 30;
// 30
console.log("Block:", z);
}
// 20
console.log("Function:", z);    
}
displayZ();
// 10
console.log("Global:", z);

Необъявленные переменные

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

function bar(){
foo = "25";
}
bar();
// 25
console.log(foo);

Несмотря на то, что вне функции bar переменная foo нигде не определяется, тем не менее она доступна вне функции во внешнем контексте. Единственное условие - мы вызываем функцию, где определена такая переменная.

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

function bar(){
foo = "25";
}
// ошибка - Uncaught ReferenceError: foo is not defined
console.log(foo);

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

function bar(){
var foo = "25";
}
bar();
// ошибка - Uncaught ReferenceError: foo is not defined
console.log(foo);

Режим strict mode

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

Преимуществом данного подхода было то, что существующий код продолжал работать. А недостатком – что любая ошибка или несовершенное решение, принятое создателями JavaScript, застревали в языке навсегда.

Так было до 2009 года, когда появился ECMAScript 5 (ES5). Он добавил новые возможности в язык и изменил некоторые из существующих. Чтобы устаревший код работал, как и раньше, по умолчанию подобные изменения не применяются. Поэтому нам нужно явно их активировать с помощью специальной директивы: "use strict".

Установить режим strict mode можно двумя способами:

  1. Добавить выражение "use strict" в начало кода JavaScript, тогда strict mode будет применяться для всего кода
  2. Добавить выражение "use strict" в начало тела функции, тогда strict mode будет применяться только для этой функции

Определение глобальных переменных в функциях может вести к потенциальным ошибкам. Чтобы их избежать используется строгий режим или strict mode:

"use strict";
function bar(){
// Uncaught ReferenceError: foo is not defined
foo = "25";     
}
bar();
console.log(foo);

В этом случае мы получим ошибку SyntaxError: Unexpected identifier, которая говорит о том, что переменная foo не определена.

Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг