Замыкание функций JavaScript


Оглавление

    Показать оглавление


Переменные JavaScript могут принадлежать к локальному или глобальная область действия.

Глобальные переменные можно сделать локальными (частными) с помощью замыканий.


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

функция может получить доступ ко всем переменным, определенным внутри функции, например:

Пример

function myFunction() {
    let a = 4;
    return a * a;
}

Попробуйте сами →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Functions</h2>
<p>A function can access variables defined inside the function:</p>

<p id="demo"></p>

<script>
myFunction();

function myFunction() {
  let a = 4;
  document.getElementById("demo").innerHTML = a * a;
}
</script>

</body>
</html>

Но функция также может обращаться к переменным, определенным вне функции, например:

Пример

let a = 4;
function myFunction() {
    return a * a;
}

Попробуйте сами →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Functions</h2>
<p>A function can access variables defined outside the function:</p>

<p id="demo"></p>

<script>
let a = 4;
myFunction();

function myFunction() {
  document.getElementById("demo").innerHTML = a * a;
} 
</script>

</body>
</html>

В последнем примере a является глобальным. переменная.

На веб-странице глобальные переменные принадлежат странице.

Глобальные переменные могут использоваться (и изменяться) всеми остальными скриптами на странице.

В первом примере a является локальным. переменная.

Локальную переменную можно использовать только внутри функции, в которой она определена. Это скрыт от других функций и другого кода сценариев.

Глобальный и локальные переменные с тем же именем разные переменные. Изменение одного не приводит к изменению другого.

Примечание

Переменные, созданные без ключевого слова объявления (var, let или const) всегда глобальные, даже если они созданы внутри функции.

Пример

function myFunction() {
  a = 4;
}

Попробуйте сами →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Functions</h2>
<p>Variables created without a declaration keyword (var, let, or const) are always global,
even if they are created inside a function.:</p>

<p id="demo"></p>

<script>
myFunction();
document.getElementById("demo").innerHTML = a * a;

function myFunction() {
  a = 4;
} 
</script>

</body>
</html>


Срок службы переменной

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

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


Противоположная дилемма

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

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

Пример

 // Initiate counter
let counter = 0;
// Function to increment 
  counter
function add() {
  counter += 1;
}
// Call add() 3 times
add();
add();
add();
// The counter should now be 3

Попробуйте сами →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Function Closures</h2>
<p>Counting with a global variable.</p>

<p id="demo"></p>

<script>
// Initiate counter
let counter = 0;

// Function to increment counter
function add() {
  counter += 1;
}

// Call add() 3 times
add();
add();
add();

// The counter should now be 3
document.getElementById("demo").innerHTML = "The counter is: " + counter;
</script>

</body>
</html>

В приведенном выше решении есть проблема: любой код на странице может изменить счетчик без вызов добавления().

Счетчик должен быть локальным для функции add(), чтобы предотвратить изменение другого кода. это:

Пример

 // Initiate counter
let counter = 0;
// Function to increment 
  counter
function add() {
  let counter = 0; 
  
  counter += 1;
}
// 
  Call add() 3 times
add();
add();
add();
//The counter should 
  now be 3. But it is 0

Попробуйте сами →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Function Closures</h2>
<p>Counting with a local variable.</p>

<p id="demo"></p>

<script>
// Initiate counter
let counter = 0;

// Function to increment counter
function add() {
  let counter = 0; 
  counter += 1;
}

// Call add() 3 times
add();
add();
add();

// The result is not 3 because you mix up the globaland local counter
document.getElementById("demo").innerHTML = "The counter is: " + counter;
</script>

</body>
</html>

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

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

Пример

 // Function to increment 
  counter
function add() {
  let counter = 0; 
  
  counter += 1;
  return counter;
}
// 
  Call add() 3 times
add();
add();
add();
//The counter should 
  now be 3. But it is 1.

Попробуйте сами →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Closures</h2>
<p>Counting with a local variable.</p>

<button type="button" onclick="myFunction()">Count!</button>

<p id="demo">0</p>

<script>
// Function to increment counter
function add() {
  let counter = 0;
  counter += 1;
  return counter;
}
// Trying to increment the counter
function myFunction(){
  document.getElementById("demo").innerHTML = add();
}
</script>

</body>
</html>

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

Внутренняя функция JavaScript может решить эту проблему.


Вложенные функции JavaScript

Все функции имеют доступ к глобальной области видимости.

Фактически, в JavaScript все функции имеют доступ к области «над» ними.

JavaScript поддерживает вложенные функции. Вложенные функции имеют доступ к область действия «выше» их.

В этом примере внутренняя функция plus() имеет доступ в переменную counter в родительской функции:

Пример

function add() {
    let counter = 0;
    function plus() {counter += 1;}
  plus();   
 
  return counter; 
}

Попробуйте сами →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Function Closures</h2>
<p>Counting with a local variable.</p>

<p id="demo">0</p>

<script>
document.getElementById("demo").innerHTML = add();
function add() {
  let counter = 0;
  function plus() {counter += 1;}
  plus();  
  return counter; 
}
</script>

</body>
</html>

Это могло бы решить дилемму счетчика, если бы мы могли достичь plus() функционировать извне.

Нам также нужно найти способ выполнить counter=0 только один раз.

Нам нужно закрытие.


Замыкания JavaScript

Помните самовызываемые функции? Что делает эта функция?

Пример

const add = (function () {
  let counter = 0;
  return function () {counter += 1; return counter}
})();
add();
add();
add();

// the counter is now 3

Попробуйте сами →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Closures</h2>

<p>Counting with a local variable.</p>

<button type="button" onclick="myFunction()">Count!</button>

<p id="demo">0</p>

<script>
const add = (function () {
  let counter = 0;
  return function () {counter += 1; return counter;}
})();

function myFunction(){
  document.getElementById("demo").innerHTML = add();
}
</script>

</body>
</html>

Объяснение примера

Переменная add присваивается возвращаемому значению самовызывающей функции. функция.

Функция самовызова запускается только один раз. Он устанавливает счетчик на ноль (0), и возвращает функциональное выражение.

Таким образом, add становится функцией. «Замечательно» то, что он может получить доступ счетчик в родительской области.

Это называется закрытием JavaScript. Это делает возможным чтобы функция имела "частные" переменные.

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

Замыкание — это функция, имеющая доступ к родительской области даже после закрытия родительской функции.