목차
JavaScript 클로저란 무엇인가요?
클로저 사용
변수 및 함수 캡슐화
데이터 캐싱
모듈화 달성
이벤트 처리
函数柯里化
异步编程
闭包的缺陷
内存泄漏问题
性能问题
보안 문제
가독성 문제
요약
웹 프론트엔드 JS 튜토리얼 JavaScript의 클로저에 대한 자세한 설명

JavaScript의 클로저에 대한 자세한 설명

Apr 24, 2023 pm 05:57 PM
javascript 프런트 엔드 폐쇄

JavaScript 클로저는 JavaScript 프로그래밍에서 널리 사용되는 중요한 개념입니다. 초보자에게는 혼란스러울 수 있지만 JavaScript 언어의 핵심을 이해하는 데 있어 핵심 개념 중 하나입니다. 이 기사에서는 JavaScript 클로저에 대해 자세히 알아보고 실제 애플리케이션에서 작동 방식과 사용 방법을 이해할 것입니다.

JavaScript의 클로저에 대한 자세한 설명

JavaScript 클로저란 무엇인가요?

JavaScript에서 클로저는 함수가 외부에 정의된 변수에 액세스할 수 있음을 의미합니다. 이러한 변수는 함수에 국한되지도 않고 함수에 대한 인수도 아니기 때문에 종종 "자유 변수"라고 합니다. 클로저는 함수 내부 또는 함수 외부에서 생성될 수 있습니다.

JavaScript의 모든 함수는 모두 자유 변수에 접근할 수 있기 때문에 클로저입니다. 함수가 호출되면 함수의 지역 변수와 매개변수를 포함하는 새로운 실행 환경이 생성됩니다. 실행 컨텍스트에는 함수가 정의된 범위에 대한 참조도 포함됩니다. 이 참조를 함수의 정의를 포함하는 모든 범위 개체의 연결된 목록인 함수의 "범위 체인"이라고 합니다. [추천 학습: javascript 비디오 튜토리얼]

함수 내에서 자유 변수에 접근해야 할 때, 먼저 해당 변수가 자신의 지역 변수에 존재하는지 확인합니다. 존재하지 않으면 변수를 찾을 때까지 범위 체인을 계속 진행합니다. 이것이 클로저의 핵심 메커니즘입니다.

간단히 말하면, 클로저는 외부 변수에 대한 참조를 포함하는 함수입니다. 이러한 변수는 함수 외부에서 정의되지만 여전히 함수 내부에서 액세스하고 조작할 수 있습니다. 클로저의 본질은 함수와 그것이 참조하는 외부 변수를 캡슐화하여 외부 간섭이 없는 환경을 형성하여 함수가 외부 변수에 접근하고 수정할 수 있도록 하는 것이며, 이러한 수정은 함수 외부의 변수에도 반영됩니다.

클로저 작동 방식을 이해하는 것은 고품질 JavaScript 코드를 작성하는 데 중요합니다. 이를 통해 변수와 함수의 범위를 더 잘 관리하고 더 복잡한 기능을 구현할 수 있습니다.

클로저 사용

변수 및 함수 캡슐화

클로저는 변수가 외부 간섭을 받지 않도록 캡슐화하는 데 사용할 수 있습니다. 이는 클로저가 함수 내부에 변수를 정의하고 해당 변수에 액세스하는 함수 외부에 함수를 생성할 수 있기 때문입니다. 이 접근 기능은 변수에 접근할 수 있으나, 외부에서 변수에 직접 접근할 수 없으므로 변수의 보안이 보장됩니다.

예를 들어, 클로저를 사용하여 카운터를 구현할 수 있습니다:

function createCounter() {
  let count = 0;
  return function() {
    count++;
    return count;
  }
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
로그인 후 복사

이 예에서는 클로저를 사용하여 카운터 변수 개수를 캡슐화하여 외부 간섭을 받지 않도록 합니다. 카운터 함수가 호출될 때마다 카운터의 다음 값을 반환합니다.

데이터 캐싱

클로저를 사용하면 함수의 계산 결과를 캐시하여 동일한 값을 여러 번 계산하는 것을 방지하여 코드 성능을 향상시킬 수 있습니다. 이 방법은 피보나치 수열과 같이 계산량이 많지만 결과가 자주 변하지 않는 함수에 적합합니다.

아래 코드 예제를 보세요:

function memoize(fn) {
  const cache = {};
  return function(...args) {
    const key = JSON.stringify(args);
    if (cache[key]) {
      return cache[key];
    } else {
      const result = fn(...args);
      cache[key] = result;
      return result;
    }
  }
}

function fibonacci(n) {
  if (n <= 1) {
    return n;
  }
  return fibonacci(n - 1) + fibonacci(n - 2);
}

const memoizedFib = memoize(fibonacci);
console.log(memoizedFib(10)); // 输出 55
console.log(memoizedFib(10)); // 输出 55,直接从缓存中读取
로그인 후 복사

이 예제에서는 함수를 매개변수로 받아들이고 클로저 함수를 반환하는 memoize 함수를 정의합니다. 클로저 함수는 함수의 계산 결과를 저장하는 데 사용되는 캐시 개체 캐시를 내부적으로 유지합니다. 클로저 함수가 호출될 때마다 전달된 매개변수를 기반으로 고유한 키 값을 생성하고 캐시에서 계산 결과를 읽으려고 시도합니다. 키 값이 캐시에 이미 존재하는 경우 캐시 결과를 직접 반환하고, 그렇지 않은 경우 전달된 함수를 호출하여 결과를 계산하고 결과를 캐시에 저장합니다. 이 접근 방식은 동일한 값을 여러 번 계산하는 것을 방지하여 코드 성능을 향상시킵니다.

모듈화 달성

클로저를 사용하면 모듈형 프로그래밍을 구현할 수 있습니다. 이 방법을 사용하면 코드를 여러 모듈로 나눌 수 있으므로 각 모듈은 해당 기능에만 집중할 수 있으므로 코드의 유지 관리성과 안전성이 향상됩니다. 동시에 클로저는 전역 변수의 오염을 방지하면서 공개 및 비공개 변수를 캡슐화할 수도 있습니다.

예를 들어, 클로저를 사용하여 간단한 모듈을 구현할 수 있습니다:

const module = (function() {
  const privateVar = &#39;I am private&#39;;
  const publicVar = &#39;I am public&#39;;
  function privateFn() {
    console.log(&#39;I am a private function&#39;);
  }
  function publicFn() {
    console.log(&#39;I am a public function&#39;);
  }
  return {
    publicVar,
    publicFn
  };
})();

console.log(module.publicVar); // 输出 &#39;I am public&#39;
module.publicFn(); // 输出 &#39;I am a public function&#39;
console.log(module.privateVar); // 输出 undefined
module.privateFn(); // 报错,无法访问私有函数
로그인 후 복사

이 예에서는 내부적으로 객체를 반환하는 즉시 실행 함수를 정의합니다. 객체에는 공용 변수와 함수뿐만 아니라 개인 변수와 함수도 포함됩니다. 이러한 방식으로 코드를 여러 모듈로 나눌 수 있으며, 각 모듈은 자체 기능에만 중점을 두어 코드의 유지 관리성과 가독성을 향상시킵니다. 동시에 개인 변수와 함수는 함수 내부에서만 볼 수 있고 외부에서는 접근 및 수정할 수 없으므로 전역 변수의 오염을 피할 수 있습니다.

이벤트 처리

다음은 이벤트 처리에 클로저를 사용하는 예입니다.

function createCounter() {
  let count = 0;

  function increment() {
    count++;
    console.log(`Clicked ${count} times`);
  }

  function decrement() {
    count--;
    console.log(`Clicked ${count} times`);
  }

  function getCount() {
    return count;
  }

  return {
    increment,
    decrement,
    getCount
  };
}

const counter = createCounter();

document.querySelector(&#39;#increment&#39;).addEventListener(&#39;click&#39;, counter.increment);
document.querySelector(&#39;#decrement&#39;).addEventListener(&#39;click&#39;, counter.decrement);
로그인 후 복사

在这个示例中,我们定义了一个名为createCounter的函数,该函数返回一个对象,该对象包含三个方法:increment,decrement和getCount。increment方法将计数器加1,decrement方法将计数器减1,getCount方法返回当前计数器的值。

我们使用createCounter函数创建了一个计数器对象counter,并将increment方法和decrement方法分别注册为加1和减1按钮的点击事件处理函数。由于increment和decrement方法内部引用了createCounter函数内部的局部变量count,因此它们形成了闭包,可以访问和修改count变量。

这个示例中,我们将计数器对象的逻辑封装在一个函数内部,并返回一个包含方法的对象,这样可以避免全局变量的使用,提高代码的可维护性和可重用性。

函数柯里化

以下是一个使用闭包实现的函数柯里化例子:

function add(x) {
  return function(y) {
    return x + y;
  }
}

const add5 = add(5); // x = 5
console.log(add5(3)); // 输出 8
console.log(add5(7)); // 输出 12
로그인 후 복사

在这个例子中,我们定义了一个名为add的函数,该函数接受一个参数x并返回一个内部函数,内部函数接受一个参数y,并返回x + y的结果。

我们使用add函数创建了一个新的函数add5,该函数的x值为5。我们可以多次调用add5函数,每次传入不同的y值进行求和运算。由于add函数返回了一个内部函数,并且内部函数引用了add函数内部的参数x,因此内部函数形成了一个闭包,可以访问和保留x值的状态。

这个例子中,我们实现了一个简单的函数柯里化,将接收多个参数的函数转化为接收一个参数的函数。函数柯里化可以帮助我们更方便地进行函数复合和函数重用。

异步编程

以下是一个使用闭包实现的异步编程的例子:

function fetchData(url) {
  return function(callback) {
    fetch(url)
      .then(response => response.json())
      .then(data => {
        callback(null, data);
      })
      .catch(error => {
        callback(error, null);
      });
  }
}

const getData = fetchData(&#39;https://jsonplaceholder.typicode.com/todos/1&#39;);
getData(function(error, data) {
  if (error) {
    console.error(error);
  } else {
    console.log(data);
  }
});
로그인 후 복사

在这个例子中,我们定义了一个名为fetchData的函数,该函数接受一个URL参数,并返回一个内部函数。内部函数执行异步操作,请求URL并将响应解析为JSON格式的数据,然后调用传入的回调函数并将解析后的数据或错误作为参数传递。

我们使用fetchData函数创建了一个getData函数,该函数请求JSONPlaceholder API的一个TODO项,并将响应解析为JSON格式的数据,然后将数据或错误传递给回调函数。由于fetchData函数返回了一个内部函数,并且内部函数引用了fetchData函数内部的URL参数和回调函数,因此内部函数形成了闭包,可以访问和保留URL参数和回调函数的状态。

这个例子中,我们使用了异步编程模型,通过将回调函数作为参数传递,实现了在异步请求完成后执行相关的操作。使用闭包可以方便地管理异步请求和相关的状态,提高代码的可读性和可维护性。

闭包的缺陷

JS 闭包具有许多优点,但也有一些缺点,包括:

内存泄漏问题

由于闭包会将外部函数的局部变量引用保存在内存中,因此如果闭包一直存在,外部函数的局部变量也会一直存在,从而导致内存泄漏。

在 JavaScript 中,闭包是指一个函数能够访问并操作其父级作用域中的变量,即便该函数已经执行完毕,这些变量仍然存在。由于闭包会引用父级作用域中的变量,因此,这些变量不会在函数执行完毕时被垃圾回收机制回收,从而占用了内存资源,这就是闭包引起内存泄漏的原因。

以下是一个闭包引起内存泄漏的示例:

function myFunc() {
  var count = 0;
  setInterval(function() {
    console.log(++count);
  }, 1000);
}

myFunc();
로그인 후 복사

在这个示例中,myFunc 函数中定义了一个变量 count,然后创建了一个计时器,在每秒钟打印 count 的值。由于计时器函数是一个闭包,它会保留对 myFunc 中的 count 变量的引用,这意味着即使 myFunc 函数执行完毕,计时器函数仍然可以访问 count 变量,从而阻止 count 变量被垃圾回收机制回收。如果我们不停地调用 myFunc 函数,将会创建多个计时器函数,每个函数都会占用一定的内存资源,最终会导致内存泄漏。

性能问题

由于闭包会在每次函数调用时创建新的作用域链,因此会增加函数的内存消耗和运行时间。在循环中创建闭包时,尤其需要注意性能问题。

在JavaScript中,每当创建一个函数时,都会为该函数创建一个新的作用域链。函数作用域链是一个指向其父级作用域的指针列表,其中包含了该函数能够访问的变量和函数。

클로저란 외부 함수의 변수와 매개변수에 액세스할 수 있고 외부 함수가 호출된 후에도 이러한 변수와 매개변수를 계속 사용할 수 있는 함수 내부에 정의된 함수를 의미합니다. 클로저가 생성되면 필요할 때 액세스할 수 있도록 외부 함수의 범위 체인에 대한 참조를 저장합니다.

클로저는 외부 함수의 범위 체인에 대한 참조를 보유하므로 각 함수 호출마다 새 범위 체인이 생성됩니다. 이는 함수가 동일한 클로저에 의해 생성되더라도 함수를 호출할 때마다 새로운 함수 범위 체인이 생성되기 때문입니다. 즉, 각 클로저에는 자체 범위 체인이 있고 클로저에 대한 각 호출은 새 범위 체인을 생성합니다.

이것이 클로저를 사용할 때 주의해야 하는 이유 중 하나입니다. 클로저를 호출할 때마다 새로운 범위 체인이 생성되므로 메모리 소비 및 성능 문제가 발생할 수 있습니다. 어떤 경우에는 메모리 누수 문제를 피하기 위해 클로저의 리소스를 수동으로 해제해야 할 수도 있습니다.

보안 문제

클로저는 외부 함수의 로컬 변수에 접근할 수 있으므로 개인 데이터가 실수로 로컬 변수에 저장되면 클로저에 의해 접근 및 수정되어 보안 문제가 발생할 수 있습니다.

가독성 문제

클로저는 변수의 수명을 연장하고 데이터를 암시적으로 전달하기 때문에 특히 여러 수준의 함수를 중첩할 때 코드를 이해하고 디버깅하기 어렵게 만들 수 있습니다.

요약

따라서 클로저는 강력한 프로그래밍 기술이지만 이를 사용할 때는 위의 단점에 주의해야 하며 코드의 유지 관리 가능성과 성능을 보장하기 위해 적절한 응용 프로그램 시나리오와 프로그래밍 스타일을 선택해야 합니다.

더 많은 프로그래밍 관련 지식을 보려면 프로그래밍 교육을 방문하세요! !

위 내용은 JavaScript의 클로저에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

C++ 람다 표현식에서 클로저의 의미는 무엇입니까? C++ 람다 표현식에서 클로저의 의미는 무엇입니까? Apr 17, 2024 pm 06:15 PM

C++에서 클로저는 외부 변수에 액세스할 수 있는 람다 식입니다. 클로저를 생성하려면 람다 표현식에서 외부 변수를 캡처하세요. 클로저는 재사용성, 정보 숨기기, 지연 평가와 같은 이점을 제공합니다. 이는 클로저가 외부 변수가 파괴되더라도 여전히 접근할 수 있는 이벤트 핸들러와 같은 실제 상황에서 유용합니다.

C++ 람다 표현식에서 클로저를 구현하는 방법은 무엇입니까? C++ 람다 표현식에서 클로저를 구현하는 방법은 무엇입니까? Jun 01, 2024 pm 05:50 PM

C++ Lambda 표현식은 함수 범위 변수를 저장하고 함수에 액세스할 수 있도록 하는 클로저를 지원합니다. 구문은 [캡처 목록](매개변수)->return-type{function-body}입니다. 캡처 목록은 캡처할 변수를 정의합니다. [=]를 사용하여 모든 지역 변수를 값으로 캡처하고, [&]를 사용하여 모든 지역 변수를 참조로 캡처하거나, [변수1, 변수2,...]를 사용하여 특정 변수를 캡처할 수 있습니다. 람다 표현식은 캡처된 변수에만 액세스할 수 있지만 원래 값을 수정할 수는 없습니다.

C++ 함수에서 클로저의 장점과 단점은 무엇입니까? C++ 함수에서 클로저의 장점과 단점은 무엇입니까? Apr 25, 2024 pm 01:33 PM

클로저는 외부 함수의 범위에 있는 변수에 액세스할 수 있는 중첩 함수입니다. 클로저의 장점에는 데이터 캡슐화, 상태 보존 및 유연성이 포함됩니다. 단점으로는 메모리 소비, 성능 영향, 디버깅 복잡성 등이 있습니다. 또한 클로저는 익명 함수를 생성하고 이를 콜백이나 인수로 다른 함수에 전달할 수 있습니다.

함수 포인터와 클로저가 Golang 성능에 미치는 영향 함수 포인터와 클로저가 Golang 성능에 미치는 영향 Apr 15, 2024 am 10:36 AM

함수 포인터와 클로저가 Go 성능에 미치는 영향은 다음과 같습니다. 함수 포인터: 직접 호출보다 약간 느리지만 가독성과 재사용성이 향상됩니다. 클로저: 일반적으로 느리지만 데이터와 동작을 캡슐화합니다. 실제 사례: 함수 포인터는 정렬 알고리즘을 최적화할 수 있고 클로저는 이벤트 핸들러를 생성할 수 있지만 성능 저하를 가져옵니다.

Go 언어 프런트엔드 기술 탐색: 프런트엔드 개발을 위한 새로운 비전 Go 언어 프런트엔드 기술 탐색: 프런트엔드 개발을 위한 새로운 비전 Mar 28, 2024 pm 01:06 PM

빠르고 효율적인 프로그래밍 언어인 Go 언어는 백엔드 개발 분야에서 널리 사용됩니다. 그러나 Go 언어를 프런트엔드 개발과 연관시키는 사람은 거의 없습니다. 실제로 프런트엔드 개발에 Go 언어를 사용하면 효율성이 향상될 뿐만 아니라 개발자에게 새로운 지평을 열어줄 수도 있습니다. 이 기사에서는 프런트엔드 개발에 Go 언어를 사용할 수 있는 가능성을 살펴보고 독자가 이 영역을 더 잘 이해할 수 있도록 구체적인 코드 예제를 제공합니다. 전통적인 프런트엔드 개발에서는 사용자 인터페이스를 구축하기 위해 JavaScript, HTML, CSS를 사용하는 경우가 많습니다.

PHP 함수의 연쇄 호출 및 폐쇄 PHP 함수의 연쇄 호출 및 폐쇄 Apr 13, 2024 am 11:18 AM

예, 체인 호출 및 클로저를 통해 코드 단순성과 가독성을 최적화할 수 있습니다. 체인 호출은 함수 호출을 유창한 인터페이스에 연결합니다. 클로저는 재사용 가능한 코드 블록을 생성하고 함수 외부의 변수에 액세스합니다.

Java에서는 클로저가 어떻게 구현됩니까? Java에서는 클로저가 어떻게 구현됩니까? May 03, 2024 pm 12:48 PM

Java의 클로저를 사용하면 외부 함수가 종료된 경우에도 내부 함수가 외부 범위 변수에 액세스할 수 있습니다. 익명의 내부 클래스를 통해 구현된 내부 클래스는 외부 클래스에 대한 참조를 보유하고 외부 변수를 활성 상태로 유지합니다. 클로저는 코드 유연성을 높이지만 익명 내부 클래스에 의한 외부 변수 참조는 해당 변수를 활성 상태로 유지하므로 메모리 누수의 위험을 인지해야 합니다.

테스트에서 golang 함수 클로저의 역할 테스트에서 golang 함수 클로저의 역할 Apr 24, 2024 am 08:54 AM

Go 언어 함수 클로저는 단위 테스트에서 중요한 역할을 합니다. 값 캡처: 클로저는 외부 범위의 변수에 액세스할 수 있으므로 테스트 매개변수를 캡처하고 중첩된 함수에서 재사용할 수 있습니다. 테스트 코드 단순화: 클로저는 값을 캡처함으로써 각 루프에 대해 매개변수를 반복적으로 설정할 필요가 없으므로 테스트 코드를 단순화합니다. 가독성 향상: 클로저를 사용하여 테스트 로직을 구성하고 테스트 코드를 더 명확하고 읽기 쉽게 만듭니다.

See all articles