목차
위 단락의 설명은 다르지만, 주의 깊게 맛보면 몇 가지 공통점을 찾을 수 있습니다. 가장 중요한 것은
주의해야 할 것은 ES6의 새로운 사양인 블록 스코프입니다. 중괄호 {} 내부에서 let, const를 사용하여 정의된 변수는 범위에 바인딩되며 중괄호 외부에서는 액세스할 수 없습니다.
사이에 임시 데드존이 있습니다(이 지점은 이 기사의 범위를 벗어납니다).
词法作用域
闭包能干啥?
如何区分闭包?
闭包真的会导致内存泄漏?
웹 프론트엔드 JS 튜토리얼 클로저에 대해 함께 알아볼까요?

클로저에 대해 함께 알아볼까요?

Sep 08, 2020 pm 01:25 PM
폐쇄

ㅋㅋㅋ ,을 만나게 됩니다. 클로저에 대한 이해는 사람마다 다릅니다. 여기서는 클로저에 대한 내 자신의 이해에 대해 이야기하겠습니다. (이해와 불일치가 있는 경우 직접 참조하세요.)

클로저에 대해 함께 알아볼까요?클로저 정의 방법

정의를 제공하기 전에 다른 사람들이 클로저를 어떻게 정의하는지 살펴보는 것이 좋습니다.

함수 객체는 범위를 통과할 수 있습니다. 체인은 서로 관련되어 있으며 함수 본문 내부의 변수는 함수 범위에 저장될 수 있습니다. 이 기능을 컴퓨터 과학 문헌에서는 "클로저"라고 합니다. - The Definitive Guide to JavaScript (6th Edition)

Closure는 A를 의미합니다. 다른 함수의 범위에 있는 변수에 액세스할 수 있는 함수입니다. 클로저를 생성하는 일반적인 방법은 다른 함수 내에 함수를 생성하는 것입니다. --JavaScript를 사용한 고급 프로그래밍(제3판)

함수가 현재 어휘 범위 밖에서 실행되더라도 함수가 자신이 속한 어휘 범위를 기억하고 액세스할 수 있을 때 클로저가 발생합니다. -- 당신이 모르는 JavaScript (1권)

위 단락의 설명은 다르지만, 주의 깊게 맛보면 몇 가지 공통점을 찾을 수 있습니다. 가장 중요한 것은

다른 범위 간의 연결

입니다. 물론 위의 정의를 직접 인용할 수도 있다(결국 위의 정의는 상대적으로 권위가 있다). 여기서 저자는 마지막 문단의 정의를 선호하며, 책 『당신이 모르는 자바스크립트(1권)』도 강력 추천한다. )'을 주의 깊게 반복해서 읽어 볼 가치가 있습니다.

클로저에 어떤 지식 포인트가 포함되어 있는지
단순히 정의하는 것만으로는 충분하지 않으며 내부적으로 어떤 지식 포인트가 포함되어 있는지 탐색해야 합니다. 저자가 유용하다고 생각하는 지식 포인트는 다음과 같습니다.

스코프 및 스코프 체인
글쎄, 사실 저자는 여러분 모두가 이에 대해 생각했다는 것을 알고 있습니다(아니요, 아무도 이것을 생각하지 않았습니다). 이제 모두가

scope

을 이해했습니다. 여기서는 이에 대해 간략하게 설명하고 그 과정을 살펴보겠습니다. 범위: 이름으로 변수를 찾는 규칙 집합입니다. 전역 범위, 블록 범위, 세 가지 유형으로 나뉩니다.

주의해야 할 것은 ES6의 새로운 사양인 블록 스코프입니다. 중괄호 {} 내부에서 let, const를 사용하여 정의된 변수는 범위에 바인딩되며 중괄호 외부에서는 액세스할 수 없습니다.

참고: 중괄호 시작 부분과 let 변수 선언

사이에 임시 데드존이 있습니다(이 지점은 이 기사의 범위를 벗어납니다).

스코프 체인: 서로 다른 스코프가 함께 갇히면 스코프 체인이 형성됩니다. 검색 방향은 내부에서 외부입니다. 스코프 검색 방향은 왜 내부에서 외부인가요? 이것은 흥미로운 질문입니다. 개인적으로 js 실행 함수가 스택에 푸시되는 방식에 따라 결정된다고 생각합니다(주제에서 조금 벗어난 느낌이 들므로 관심 있는 친구는 정보를 확인할 수 있습니다).

어휘 범위

함수가 다른 함수 범위의 변수에 접근할 수 있는 이유(또는 현재 범위를 기억하고 현재 범위 밖에서 접근할 수 있는 이유)핵심는 <code>어휘 범위가 작동 중임을 나타냅니다. 이것은 매우 중요하지만 모든 사람이 이 지식 포인트를 아는 것은 아닙니다. 여기서 간단히 논의해 보겠습니다.

프로그래밍 세계에는 두 가지 작업 모드가 있습니다. 하나는 대부분의 프로그래밍 언어에서 사용되는 어휘 범위이고, 다른 하나는 반대되는 동적 범위입니다. (이것은 이 기사의 범위를 벗어납니다.) {}里面使用let,const定义的变量,都会绑定到该作用范围内,花括号以外的地方无法访问。注意:在花括号开始 到 let变量声明之前,存在暂时性死区(该点不在本文讨论范围)。

作用域链:当不同的作用域 (混~淆~在~一~起~ 呸,不小心出戏了) 圈套在一起时,就形成了作用域链。注意的是,查找方向是从内到外的。

为什么作用域的查找方向是从内到外的呢?这是个很有趣的问题。个人觉得是跟js执行函数的入栈方式决定的(感觉有点偏题了,有兴趣的小伙伴可以去查一下资料)。

词法作用域

函数之所以 可以访问另一个函数作用域的变量(或者说记住当前的作用域并在当前以外的地方访问)的关键点就是词法作用域在起作用。这一点很重要,但不是所有人都知道这个知识点,这里简单探讨一下。

在编程界中,存在两种作用域工作模式,一种是被大多数编程语言所采用的词法作用域;另一种就是与其相反的动态作用域(这个不在本文的讨论范围)。

词法作用域: 变量和块的作用域 在 您编写代码的阶段 就已经确定好了,不会随着调用的对象或者地方的不同而改变(感觉跟this相反)。

要不,举个栗子看看吧:

let a = 1;
function fn(){
    let a = 2;
    function fn2(){
        console.log(a);
    }
 return fn2;
}

let fn3 = fn();
fn3();
로그인 후 복사

从上面的定义可以知道,fn是一个闭包函数,fn3拿到了fn2的指针地址,当fn3执行的时候,其实是执行fn2,而里面的a变量,根据作用域链的查找规则,找到的是fn作用域内的变量a

클로저에 대해 함께 알아볼까요? 어휘 범위: 변수와 ​​블록의 범위는 코드를 작성할 때 이미 결정되어 있으며 호출하는 객체나 위치에 따라 변경되지 않습니다(이와 반대되는 느낌입니다).
예를 들어보면

function Fn(obj){
    with(obj){
        a = 2;
    }
}

var o1 = {
    a:1
}
var o2 = {
    b:1
}

Fn(o1);
console.log(o1.a); //2
Fn(o2);
console.log(o2.a); //undefined;
console.log(a); //2 a被泄漏到全局里面去了
// 这是with的一个副作用, 如果当前词法作用域没有该属性,会在全局创建一个
로그인 후 복사
로그인 후 복사

위의 정의에서 fn이 클로저 함수이고 fn3 포인터 주소를 얻는다는 것을 알 수 있습니다. fn2fn3가 실행되면 실제로 fn2가 실행되고 범위에 따라 내부에 a 변수가 검색됩니다. 체인의 규칙은 fn 범위에서 변수 a를 찾으므로 최종 출력은 1이 아닌 2입니다. (아래 그림을 볼 수 있습니다)

🎜🎜🎜🎜🎜주제에서 벗어나, 어휘 범위를 속이는 방법은 무엇입니까? 🎜🎜어휘 범위는 정적이지만 동적 효과를 얻기 위해 속이는 방법이 여전히 있습니다. 🎜

第一种方法是使用eval. eval可以把字符串解析成一个脚本来运行,由于在词法分析阶段,无法预测eval运行的脚本,所以不会对其进行优化分析。

第二种方法是with. with通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。with本身比较难掌握,使用不当容易出现意外情况(如下例子),不推荐使用 -.-

function Fn(obj){
    with(obj){
        a = 2;
    }
}

var o1 = {
    a:1
}
var o2 = {
    b:1
}

Fn(o1);
console.log(o1.a); //2
Fn(o2);
console.log(o2.a); //undefined;
console.log(a); //2 a被泄漏到全局里面去了
// 这是with的一个副作用, 如果当前词法作用域没有该属性,会在全局创建一个
로그인 후 복사
로그인 후 복사

闭包能干啥?

闭包的使用场景可多了,平时使用的插件或者框架,基本上都有闭包的身影,可能您没留意过罢了。下面笔者列举一些比较常见的场景。

  1. 模拟私有变量和方法,进一步来说可以是模拟模块化;目前常用的AMD,CommonJS等模块规范,都是利用闭包的思想;

  2. 柯里化函数或者偏函数;利用闭包可以把参数分成多次传参。如下面代码:

// 柯里化函数
function currying(fn){
    var allArgs = [];

    function bindCurry(){
        var args = [].slice.call(arguments);
        allArgs = allArgs.concat(args);
        return bindCurry;
    }
    bindCurry.toString = function(){
        return fn.apply(null, allArgs);
    };

    return bindCurry;
}
로그인 후 복사
  1. 实现防抖或者节流函数;

  2. 实现缓存结果(记忆化)的辅助函数:

// 该方法适合缓存结果不易改变的函数
const memorize = fn => {
    let memorized = false;
    let result = undefined;
    return (...args) => {
        if (memorized) {
            return result;
        } else {
            result = fn.apply(null,args); 
            memorized = true;
            fn = undefined;
            return result;
        }
    };
};
로그인 후 복사

如何区分闭包?

说了那么多,我怎么知道自己写的代码是不是闭包呢?先不说新手,有些代码的确隐藏的深,老鸟不仔细看也可能发现不了。 那有没有方法可以帮助我们区分一个函数是不是闭包呢?答案是肯定的,要学会善于利用周边的工具资源,比如浏览器。

打开常用的浏览器(chrome或者其他),在要验证的代码中打上debugger断点,然后看控制台,在scope里面的Closure(闭包)里面是否有该函数(如下图)。

클로저에 대해 함께 알아볼까요?

闭包真的会导致内存泄漏?

答案是有可能。内存泄漏的原因在于垃圾回收(GC)无法释放变量的内存,导致运行一段时候后,可用内存越来越少,最终出现内存泄漏的情况。常见的内存泄漏场景有4种:全局变量;闭包引用;DOM事件绑定;不合理使用缓存。其中,闭包导致内存泄漏都是比较隐蔽的,用肉眼查看代码判断是比较难,我们可用借助chrome浏览器的Memory标签栏工具来调试。由于篇幅问题,不展开说明了,有兴趣自己去了解一下如何使用。

想了解更多编程学习,敬请关注php培训栏目!

위 내용은 클로저에 대해 함께 알아볼까요?의 상세 내용입니다. 자세한 내용은 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. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 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

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

클로저로 인한 메모리 누수 문제 해결 클로저로 인한 메모리 누수 문제 해결 Feb 18, 2024 pm 03:20 PM

제목: 클로저로 인한 메모리 누수 및 솔루션 소개: 클로저는 내부 함수가 외부 함수의 변수에 액세스할 수 있도록 하는 JavaScript에서 매우 일반적인 개념입니다. 그러나 클로저를 잘못 사용하면 메모리 누수가 발생할 수 있습니다. 이 문서에서는 클로저로 인해 발생하는 메모리 누수 문제를 살펴보고 솔루션과 구체적인 코드 예제를 제공합니다. 1. 클로저로 인한 메모리 누수 클로저의 특징은 내부 함수가 외부 함수의 변수에 접근할 수 있다는 것입니다. 즉, 클로저에서 참조되는 변수는 가비지 수집되지 않습니다. 부적절하게 사용하는 경우,

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

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

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

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

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

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

클로저에서 메모리 누수를 효과적으로 방지하는 방법은 무엇입니까? 클로저에서 메모리 누수를 효과적으로 방지하는 방법은 무엇입니까? Jan 13, 2024 pm 12:46 PM

클로저에서 메모리 누수를 방지하는 방법은 무엇입니까? 클로저는 함수 중첩 및 데이터 캡슐화를 가능하게 하는 JavaScript의 가장 강력한 기능 중 하나입니다. 그러나 클로저는 특히 비동기 및 타이머를 처리할 때 메모리 누수가 발생하기 쉽습니다. 이 문서에서는 클로저에서 메모리 누수를 방지하는 방법을 설명하고 구체적인 코드 예제를 제공합니다. 메모리 누수는 일반적으로 객체가 더 이상 필요하지 않지만 어떤 이유로 객체가 차지하는 메모리를 해제할 수 없을 때 발생합니다. 클로저에서 함수가 외부 변수를 참조하고 이러한 변수는

See all articles