Вступ до сфери застосування в JavaScript

Область дії визначає час життя та видимість змінної. Змінні не видно поза тим обсягом, в якому вони оголошені.

JavaScript має модуль, область функцій, область блоків, лексичну сферу та глобальну область.

Глобальний обсяг

Змінні, визначені поза будь-якою функцією, блоком або сферою дії модуля, мають глобальну область дії. До змінних у глобальному масштабі можна отримати доступ звідусіль у програмі.

Коли модульна система ввімкнена, важче створювати глобальні змінні, але все одно це можна зробити. Визначивши змінну в HTML, поза будь-якою функцією, можна створити глобальну змінну:

 let GLOBAL_DATA = { value : 1};  console.log(GLOBAL_DATA);

Коли немає модульної системи, набагато простіше створювати глобальні змінні. Змінна, оголошена поза будь-якою функцією, у будь-якому файлі, є глобальною змінною.

Глобальні змінні доступні протягом усього терміну роботи програми.

Іншим способом створення глобальної змінної є використання windowглобального об'єкта в будь-якому місці програми:

window.GLOBAL_DATA = { value: 1 };

На цей момент GLOBAL_DATAзмінна видно скрізь.

console.log(GLOBAL_DATA)

Як ви можете собі уявити, ці практики є поганими.

Сфера застосування модуля

До модулів змінна, оголошена поза будь-якою функцією, була глобальною змінною. У модулях змінна, оголошена поза будь-якою функцією, прихована і недоступна для інших модулів, якщо вона явно не експортована.

Експорт робить функцію або об’єкт доступними для інших модулів. У наступному прикладі я експортую функцію з sequence.jsфайлу модуля:

// in sequence.js export { sequence, toList, take };

Імпорт робить функцію чи об'єкт з інших модулів доступними для поточного модуля.

import { sequence, toList, toList } from "./sequence";

Певним чином, ми можемо уявити модуль як самовиконуючуся функцію, яка приймає дані імпорту як вхідні дані та повертає дані експорту.

Сфера функцій

Область дії означає, що параметри та змінні, визначені у функції, видно всюди в межах функції, але не видно за межами функції.

Розглянемо наступну функцію, яка виконується автоматично, під назвою IIFE.

(function autoexecute() { let x = 1; })(); console.log(x); //Uncaught ReferenceError: x is not defined

IIFE розшифровується як Вираз функції відразу ж викликаного і є функцією, яка запускається відразу після її визначення.

Змінні, оголошені з, varмають лише область функцій. Навіть більше, змінні, оголошені за допомогою var, піднімаються у верхній частині області дії. Таким чином вони можуть отримати доступ до їх оголошення. Погляньте на код нижче:

function doSomething(){ console.log(x); var x = 1; } doSomething(); //undefined

Цього не трапляється для let. До змінної, оголошеної з, letможна отримати доступ лише після її визначення.

function doSomething(){ console.log(x); let x = 1; } doSomething(); //Uncaught ReferenceError: x is not defined

Змінна, оголошена з, varможе бути повторно оголошена кілька разів в одному і тому ж обсязі. Наступний код чудово підходить:

function doSomething(){ var x = 1 var x = 2; console.log(x); } doSomething();

Змінні, декларовані letабо constне можуть бути повторно оголошені в одному обсязі:

function doSomething(){ let x = 1 let x = 2; } //Uncaught SyntaxError: Identifier 'x' has already been declared

Можливо, нам навіть не потрібно про це дбати, оскільки varце почало застарівати.

Блок Сфера

Обсяг блоку визначається фігурними дужками. Він розділений {і }.

Змінні, оголошені letта constможуть мати область блоку. Доступ до них можливий лише в тому блоці, в якому вони визначені.

Розглянемо наступний код, який підкреслює letобласть блоку:

let x = 1; { let x = 2; } console.log(x); //1

На відміну від цього, varдекларація не має блокової області:

var x = 1; { var x = 2; } console.log(x); //2

Ще однією поширеною проблемою відсутності області блоку є використання асинхронної операції, як setTimeout()у циклі. Текучий код циклу відображає число 5, п'ять разів.

(function run(){ for(var i=0; i<5; i++){ setTimeout(function logValue(){ console.log(i); //5 }, 100); } })();

The for loop statement, with the let declaration, creates a new variable locale to the block scope, for each iteration. The next loop code shows 0 1 2 3 4 5.

(function run(){ for(let i=0; i<5; i++){ setTimeout(function log(){ console.log(i); //0 1 2 3 4 }, 100); } })();

Lexical Scope

Lexical scope is the ability of the inner function to access the outer scope in which it is defined.

Consider the next code:

(function autorun(){ let x = 1; function log(){ console.log(x); }; function run(fn){ let x = 100; fn(); } run(log);//1 })();

The log function is a closure. It refers the x variable from its parent function autorun(), not the one from the run() function.

The closure function has access to the scope in which it was created, not the scope in which it was executed.

The local function scope of autorun() is the lexical scope of the log() function.

Scope chain

Every scope has a link to the parent scope. When a variable is used, JavaScript looks down the scope chain until it either finds the requested variable or until it reaches the global scope, which is the end of the scope chain.

Look at the next example:

let x0 = 0; (function autorun1(){ let x1 = 1; (function autorun2(){ let x2 = 2; (function autorun3(){ let x3 = 3; console.log(x0 + " " + x1 + " " + x2 + " " + x3);//0 1 2 3 })(); })(); })();

The autorun3() inner function has access to the local x3 variable. It has also access to the x1 and x2 variables from the outer functions and the x0 global variable.

If it cannot find the variable, it will return an error in strict mode.

"use strict"; x = 1; console.log(x) //Uncaught ReferenceError: x is not defined

In non-strict mode, referred to as “sloppy mode”, it will do a bad thing and create a global variable.

x = 1; console.log(x); //1

Conclusion

Variables defined in global scope are available everywhere in the application.

In a module, a variable declared outside any function is hidden and not available to other modules unless it is explicitly exported.

Function scope means that parameters and variables defined in a function are visible everywhere within the function

Variables declared with let and const have block scope. var doesn’t have block scope.

Discover Functional JavaScript was named one of thebest new Functional Programming books by BookAuthority!

For more on applying functional programming techniques in React take a look atFunctional React.

Learn functional React, in a project-based way, with Functional Architecture with React and Redux.

Follow on Twitter