Область видимости в JS
оригинал тут https://itchief.ru/javascript/scope-and-context
В JS есть глоальная и локальные области видимости
Переменные объявленные внутри блока, не могут быть доступны в глобальной области...
if (true) {
// локальная переменная
let b = 17;
console.log(b); // 17
}
console.log(b); // Uncaught ReferenceError: b is not defined
Но если мы объявим переменную в глобальной области видимости, то она будет доступна внутри блока, и может быть изменена от туда.
let b = 0;
if (true) {
b = 17;
console.log(b); // 17
}
console.log(b); // 17
Это происходит потому что если JS не находит переменную в своей области видимости, то он ищет её в родительской, если её нету и там, то ещё выше, и так пока не доберётся до глабальной области видимости.
// глобальная область видимости
let a = 5;
let b = 8;
let c = 20;
function fnA() {
a = 7;
b = 10;
let b = 11;
b = 13;
function fnB() {
let c = 25;
console.log(a); // 7
console.log(b); // 13
console.log(c); // 25
}
fnB();
}
fnA();

Значение переменной на момент вызова
Важно что в отличии от PHP, JS берёт значение переменной согласно состоянию лексического окружения на момент вызова функции а не на момент её создания...
let name = 'Gizmo';
function sayName(){
console.log(name);
}
name = 'Overfinch';
sayName(); //Overfinch
Родительская область а не стэк вызова
Так же важно что JS ищет переменные не возвращаясь по стеку вызова, а поднимаясь в родительскую область вызова.
let userName = "Peter";
function sayUserName() {
console.log(userName);
}
function sayUserNameAgain() {
let userName = "Sarah";
sayUserName();
}
sayUserNameAgain(); // Peter
Устаревшее ключевое слово var
var
В отличии от let, var ограничевается только функцией, но может быть доступной за пределами блока.
if (true) {
var b = 17;
}
console.log(b);
Вложенные области видимости и var
var
// Global variable
const userName = "Peter";
// Outer function
function calcAge(birthyear) {
const currentYear = 2021;
const age = currentYear - birthyear;
// inner block
if (age <= 60) {
var working = true;
const message = \`Peter is still employed!\`;
console.log(message);
}
// inner function
function yearsToRetire() {
const retirement = 60 - age;
console.log(\`${userName} will be retired in ${retirement} years!\`);
}
yearsToRetire();
}
calcAge(1975);

Здесь var working
транслируется в родительскую "зелёную" область видимости, а из неё доступен так же для функции yearsToRetire()
Last updated