Для установки нажмите кнопочку Установить расширение. И это всё.

Исходный код расширения WIKI 2 регулярно проверяется специалистами Mozilla Foundation, Google и Apple. Вы также можете это сделать в любой момент.

4,5
Келли Слэйтон
Мои поздравления с отличным проектом... что за великолепная идея!
Александр Григорьевский
Я использую WIKI 2 каждый день
и почти забыл как выглядит оригинальная Википедия.
Статистика
На русском, статей
Улучшено за 24 ч.
Добавлено за 24 ч.
Что мы делаем. Каждая страница проходит через несколько сотен совершенствующих техник. Совершенно та же Википедия. Только лучше.
.
Лео
Ньютон
Яркие
Мягкие

Замыкание (программирование)

Из Википедии — свободной энциклопедии

Замыкание (англ. closure) в программировании — функция первого класса, в теле которой присутствуют ссылки на переменные, объявленные вне тела этой функции в окружающем коде и не являющиеся её параметрами. Говоря другим языком, замыкание — функция, которая ссылается на свободные переменные в своей области видимости.

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

Замыкание — это особый вид функции. Она определена в теле другой функции и создаётся каждый раз во время её выполнения. Синтаксически это выглядит как функция, находящаяся целиком в теле другой функции. При этом вложенная внутренняя функция содержит ссылки на локальные переменные внешней функции. Каждый раз при выполнении внешней функции происходит создание нового экземпляра внутренней функции, с новыми ссылками на переменные внешней функции.

В случае замыкания ссылки на переменные внешней функции действительны внутри вложенной функции до тех пор, пока работает вложенная функция, даже если внешняя функция закончила работу, и переменные вышли из области видимости.[1]

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

Примеры

Больше примеров смотрите в викиучебнике.

В языке Scheme

(define (make-adder n)       ; возвращает замкнутое лямбда-выражение
  (lambda (x)                ; в котором x - связанная переменная,
    (+ x n)                  ; а n - свободная (захваченная из внешнего контекста)
  )
)                

(define add1 (make-adder 1)) ; делаем процедуру для прибавления 1
(add1 10)                    ; вызываем её, возвращает 11

(define sub1 (make-adder -1)); делаем процедуру для вычитания 1
(sub1 10)                    ; вызываем её, возвращает 9

В языке JavaScript[2]

'use strict';

const add = function(x) {
  return function(y) {
    const z = x + y;
    console.log(x + '+' + y + '=' + z);
    return z;
  };
};

const res = add(3)(6); // вернёт 9 и выведет в консоль 3+6=9

console.log(res);

Этот же код в версии ECMAScript2015 с использованием "стрелочных функций":

'use strict';

const add = x => y => {
  const z = x + y;
  console.log(x + '+' + y + '=' + z);
  return z;
};

const res = add(3)(6); // вернёт 9 и выведет в консоль 3+6=9

console.log(res);

Пояснение: в JavaScript сочетание => является оператором объявления стрелочной функции, см например https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions. Здесь в константу add помещается функция от аргумента x, результатом которой будет являться другая функция, а именно функция от аргумента y, результат которой вычисляется приведённым в фигурных скобках блоком кода. Этот блок кода опирается на аргумент y своей функции и на замыкание, создаваемое для аргумента x внешней функции.

При вызове add(3)(6) функция, хранящаяся в переменной add, вызывается с аргументом 3 и возвращает функцию, завязанную на значение 3 в замыкании x.

Далее в рамках такого обращения эта функция выполняется с аргументом y = 6 и возвращает 9.

Можно сделать рекурсивное замыкание:

'use strict';

const add = x => y => {
  const z = x + y;
  console.log(x + '+' + y + '=' + z);
  return add(z);
};

const res = add(1)(4)(6)(9);

console.log(res);
/* 1+4=5
   5+6=11
   11+9=20
   [Function]*/

Когда JS-код работает — локальные переменные хранятся в scope. В JavaScript локальные переменные могут оставаться в памяти даже после того, как функция вернула значение.

Все функции в JavaScript это замыкания, то есть всегда, когда создается функция — всегда создается замыкание, хоть и зачастую оно пустое, так как функции обычно из объявления контекста как правило ничего не используют. Но нужно понимать разницу между созданием замыкания и созданием нового scope-объекта: замыкание (функция + ссылка на текущую цепочку scope-объектов) создается при определении функции, но новый scope-объект создается (и используется для модификации цепочки scope-объектов замыкания) при каждом вызове функции.

В языке PHP

В PHP замыкания - это анонимные функции, особые конструкции, которые позволяют описывать функции, не имеющие определённых имён.

<?php

function add($x) {
    return function ($y) use ($x) { // <-- анонимная функция (замыкание)
        return $x + $y;
    }; // <-- эта точка с запятой здесь нужна!
}

echo add(3)(5) . PHP_EOL;   // Выведет: 8

$f = add(3);
var_dump($f);               // Выведет: object(Closure)
echo $f(6) . PHP_EOL;       // Выведет: 9

В PHP наследование переменных из родительской области видимости осуществляется с помощью конструкции use путем явного указания имен наследуемых переменных.

Другой пример с передачей замыкания в метод, где ожидается callable-параметр:

<?php

function power($arr, $exp) {
    // переменная $func будет хранить ссылку на объект класса Closure, который описывает наше замыкание
    $func = function ($el) use ($exp) {
        return $el ** $exp;
    };
    
    return array_map($func, $arr);
}

$list = [1, 3, 4];

var_dump(power($list, 2)); // Выведет: array(3) {[0]=>int(1) [1]=>int(9) [2]=>int(16)}
var_dump(power($list, 3)); // Выведет: array(3) {[0]=>int(1) [1]=>int(27) [2]=>int(64)}


См. также

Примечания

Эта страница в последний раз была отредактирована 1 июля 2021 в 10:40.
Как только страница обновилась в Википедии она обновляется в Вики 2.
Обычно почти сразу, изредка в течении часа.
Основа этой страницы находится в Википедии. Текст доступен по лицензии CC BY-SA 3.0 Unported License. Нетекстовые медиаданные доступны под собственными лицензиями. Wikipedia® — зарегистрированный товарный знак организации Wikimedia Foundation, Inc. WIKI 2 является независимой компанией и не аффилирована с Фондом Викимедиа (Wikimedia Foundation).