Рубрики
Без рубрики

Как использовать закрытие в JavaScript – руководство для начинающих

Замыкание – это запутанная концепция JavaScript, чтобы узнать, потому что трудно увидеть, как они на самом деле используются. В отличие от других концепций, таких как функции, переменные и объекты, вы не всегда используете замыкание добросовестно и напрямую. Вы не говорите: О! Здесь я буду использовать закрытие как решение. Но на то

Автор оригинала: FreeCodeCamp Community Member.

Замыкание – это запутанная концепция JavaScript, чтобы узнать, потому что трудно увидеть, как они на самом деле используются.

В отличие от других концепций, таких как функции, переменные и объекты, вы не всегда используете замыкание добросовестно и напрямую. Вы не говорите: О! Здесь я буду использовать закрытие как решение.

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

Что такое закрытие в JavaScript?

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

const value = 1
function doSomething() {
    let data = [1,2,3,4,5,6,7,8,9,10,11]
    return data.filter(item => item % value === 0)
}

Вот функция Досметочное использует переменную ценность Отказ Но и функция Элемент => Элемент% Значение Затем можно записать так:

function(item){
    return item % value === 0
}

Вы используете значение переменной ценность это было определено за пределами самой функции.

Функции могут получить доступ к значениям вне контекста

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

let count = 1
function counter() {
    console.log(count)
}
counter() // print 1
count = 2
counter() // print 2

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

Почему мы используем функции?

Но почему мы используем функции в наших программах? Конечно, можно – сложно, но возможно – написать программу без использования функций, которые мы определяем. Так почему же мы создаем правильные функции?

Представьте себе кусок кода, который делает что-то замечательное, что угодно и состоит из x количество строк.

/* My wonderful piece of code */

Теперь предположим, что вы должны использовать этот Прекрасный кусок кода В разных частях вашей программы, что бы вы сделали?

«Натуральный» вариант состоит в том, чтобы соединить этот кусок кода в набор, который может быть многоразовым, и этот многоразовый набор – это то, что мы называем функцией. Функции – лучший способ повторно использовать и обмениваться кодом в рамках программы.

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

Но где находится закрытие?

Используя счетчик пример, давайте рассмотрим, что как Прекрасный кусок кода.

let count = 1
function counter() {
    console.log(count)
}
counter() // print 1

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

function wonderfulFunction() {
    let count = 1
    function counter() {
        console.log(count)
    }
    counter() // print 1
}

Теперь, что у нас есть? Функция: счетчик который использует значение, которое было объявлено вне этого Считать Отказ И значение: Считать это было объявлено в замечательная функция Функция сферы, но используется внутри счетчик функция.

То есть у нас есть функция, которая использует значение, которое было объявлено вне своего контекста: закрытие Отказ

Просто, не так ли? Теперь, что происходит, когда функция замечательная функция выполняется? Что происходит с переменной Считать и функция счетчик Однажды родитель Функция выполняется?

Переменные и функции, объявленные в его теле «Исчезать» (уборщик мусора).

Теперь давайте модифицируем пример немного:

function wonderfulFunction() {
    let count = 1
    function counter() {
        count++
        console.log(count)
    }
   setInterval(counter, 2000)
}
wonderfulFunction()

Что произойдет сейчас для переменной и функции, объявленной внутри замечательная функция ?

В этом примере мы говорим браузеру запустить счетчик каждые 2 секунды. Таким образом, JavaScript Engine должен поддерживать ссылку на функцию, а также для переменной, которая используется им. Даже после родительской функции замечательная функция Заканчивает свой цикл выполнения, функция счетчик и значение стоимости все равно ” live” Отказ

Этот «эффект» наличия замыкания происходит, потому что JavaScript поддерживает вложение функций. Или другими словами, функции – это Первый класс граждан На языке, и вы можете использовать их как любой другой объект: вложенные, переданные как аргумент, как значение возврата, и так далее.

Что я могу сделать с закрытиями в JavaScript?

Немедленно вызываемая функция выражения (IIFE)

Это техника, которая много использовалась в DES5 дней для реализации структуры дизайна «Модуль» (до того, как это было первоначально поддерживается). Идея состоит в том, чтобы «обернуть» ваш модуль в функции, которая немедленно выполняется.

(function(arg1, arg2){
...
...
})(arg1, arg2)

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

const module = (function(){
	function privateMethod () {
	}
	const privateValue = "something"
	return {
	  get: privateValue,
	  set: function(v) { privateValue = v }
	}
})()

var x = module()
x.get() // "something"
x.set("Another value")
x.get() // "Another Value"
x.privateValue //Error

Функциональная фабрика

Другой рисунок дизайна реализован благодаря закрытиям – это «функциональная фабрика». Это когда функции создают функции или объекты, например, функция, которая позволяет создавать пользовательские объекты.

const createUser = ({ userName, avatar }) => ({
      id: createID(),
      userName,
      avatar,
      changeUserName (userName) {
        this.userName = userName;
        return this;
      },
      changeAvatar (url) {
        // execute some logic to retrieve avatar image
        const newAvatar = fetchAvatarFromUrl(url)
        this.avatar = newAvatar
        return this
      }
    });
    
        console.log(createUser({ userName: 'Bender', avatar: 'bender.png' }));
    
    {
      "id":"17hakg9a7jas",
      "avatar": "bender.png",
      "userName": "Bender",
      "changeUsername": [Function changeUsername]
      "changeAvatar": [Function changeAvatar]
    
    }
    */c

И используя этот шаблон, вы можете реализовать идею от функционального программирования, называемого Carrying Отказ

Карри

Carrying – это рисунок дизайна (и характеристика некоторых языков), где функция немедленно оценивается и возвращает вторую функцию. Этот шаблон позволяет выполнять специализацию и состав.

Вы создаете эти «карманные» функции, использующие замыкание, определяющие и возвращение внутренней функции закрытия.

function multiply(a) {

    return function (b) {
        return function (c)  {
            return a * b * c
        }
    }
}
let mc1 = multiply(1);
let mc2 = mc1(2);
let res = mc2(3);
console.log(res);

let res2 = multiply(1)(2)(3);
console.log(res2);

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

let multiply = (a) => (b) => (c) => {

    return a * b * c;
}

let mc1 = multiply(1);
let mc2 = mc1(2);
let res = mc2(3);
console.log(res);

let res2 = multiply(1)(2)(3);
console.log(res2);

Где мы можем применить карри? В составе, скажем, у вас есть функция, которая создает HTML-элементы.

function createElement(element){
    const el = document.createElement(element)
    return function(content) {
        return el.textNode = content
    }
}

const bold = crearElement('b')
const italic = createElement('i')
const content = 'My content'
const myElement  = bold(italic(content)) // My content

Прослушиватели событий

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

Предположим, вы используете стороннюю библиотеку, чтобы сделать элементы в вашем сборе данных. Эта библиотека открывает компонент под названием Рендеритм у этого есть только одна доступная опора OnClick Отказ Этот опор не получает никаких параметров и не возвращает значение.

Теперь в вашем конкретном приложении вам требуется, когда пользователь нажимает на элементе, приложение отображает оповещение с заголовком элемента. Но OnClick Событие, которое у вас есть доступно, не принимает аргументы – так что вы можете сделать? Замыкание к спасению :

// Closure
// with es5
function onItemClick(title) {
    return function() {
      alert("Clicked " + title)
    }
}
// with es6
const onItemClick = title => () => alert(`Clcked ${title}`)

return (
  
{items.map(item => {
return (
   
    {item.title}
  
)
})}

)

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

Заключение

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

Закрытие – одна из тех концепций, которые могут быть трудно понять, когда вы начинаете. Но как только вы знаете, что вы используете их и понимаете их, это позволяет увеличить ваши инструменты и продвигать вашу карьеру.

🐦 Следуй за мной в Twitter ✉️ Присоединиться к рассылке ❤️ Поддерживая мою работу