웹 프론트엔드 JS 튜토리얼 자바스크립트의 모듈화: 캡슐화(클로저), 상속(프로토타입) 소개_javascript 기술

자바스크립트의 모듈화: 캡슐화(클로저), 상속(프로토타입) 소개_javascript 기술

May 16, 2016 pm 05:28 PM
javascript 캡슐화 모듈식 상속하다 폐쇄

JavaScript는 본질적으로 캐주얼하지만 브라우저가 점점 더 많은 일을 할 수 있게 되면서 언어는 점점 더 심각해지고 있습니다. 복잡한 논리 하에서 JavaScript는 모듈화되어야 하며 모듈은 캡슐화되어야 하며 외부 호출을 위한 인터페이스만 남겨 두어야 합니다. 클로저(Closure)는 자바스크립트에서 모듈 캡슐화의 핵심이며, 많은 초보자들이 이해하기 어려워하는 포인트이기도 합니다. 처음에는 혼란스러웠습니다. 이제 나는 이 개념을 더 깊이 이해하게 되었다고 확신합니다. 이해를 돕기 위해 기사에서는 비교적 간단한 개체를 캡슐화하려고 시도합니다.

우리는 페이지에서 n 값을 유지하는 카운터 개체 티커를 유지하려고 합니다. 사용자가 작업을 수행하면 카운트를 증가시킬 수 있지만(n 값에 1을 더함) n을 감소시키거나 n을 직접 변경할 수는 없습니다. 게다가 우리는 때때로 이 값을 쿼리해야 합니다.

개방형 JSON 스타일 모듈화

문을 여는 방법은

코드를 복사하세요 코드는 다음과 같습니다.

var Ticker = {
n:0,
Tick:function(){
this.n ;
},
};

이러한 작성 방식은 자연스럽고 효과적입니다. 개수를 늘려야 하는 경우에는 ticket.tick() 메서드를 호출합니다. 개수를 쿼리해야 하는 경우에는 ticket.n 변수에 액세스합니다. 그러나 단점도 분명합니다. 모듈 사용자는 Ticker.n-- 또는 Ticker.n=-1을 호출하는 등 자유롭게 n을 변경할 수 있습니다. 티커를 캡슐화하지 않았습니다. n 및 진드기()는 티커의 "구성원"으로 보이지만 해당 접근성은 티커와 동일하며 전역적입니다(티커가 전역 변수인 경우). 캡슐화 측면에서 이 모듈식 접근 방식은 다음 접근 방식보다 약간 더 우스꽝스럽습니다(일부 간단한 애플리케이션의 경우 이 정도만으로도 충분합니다).

코드 복사 코드는 다음과 같습니다.

var ticket = {};
var ticketerN = 0;
var ticketerTick = function(){
ticketerN ;
}

tickerTick();

tick()에서 this.n에 액세스한다는 점은 주목할 가치가 있습니다. 이는 n이 Ticker의 멤버이기 때문이 아니라 Tick()을 호출하는 Ticker이기 때문입니다. 실제로, 여기에ticker.n을 작성하는 것이 더 나을 것입니다. 왜냐하면 진드기()가 호출되면 이는 티커가 아니라 다음과 같은 다른 것이기 때문입니다.

코드 복사 코드는 다음과 같습니다.

var func = Ticker.tick;
func( );

이때 실제로는 Tick()을 호출하는 것이 윈도우인데, 함수가 실행되면 window.n에 접근을 시도하여 오류가 발생하게 됩니다.

실제로 이러한 "개방형" 모듈식 접근 방식은 프로그램보다는 JSON 스타일 데이터를 구성하는 데 자주 사용됩니다. 예를 들어, 다음 JSON 객체를 Ticker 함수에 전달하여 티커가 100부터 계산을 시작하고 매번 2씩 증가하는지 확인할 수 있습니다.

코드 복사 코드는 다음과 같습니다.

var config = {
nStart: 100,
단계:2
}

스코프 체인 및 클로저
다음 코드를 보면 config를 전달하여 티커 사용자 정의를 구현했습니다.

코드 복사 코드는 다음과 같습니다.

함수 티커(config){
var n = config.nStart;
function 진드기(){
n = config.step;
}
}
console.log(ticker.n) // ->undefine

티커가 객체에서 함수로 변경된 이유가 궁금하실 수도 있습니다. 이는 JavaScript에서는 함수에만 범위가 있고, 함수 내부 변수는 함수 본문 외부에서 액세스할 수 없기 때문입니다. Ticker() 외부에서 Ticker.n에 ​​액세스하면 정의되지 않은 결과가 발생하지만, Tick() 내에서 n에 액세스하면 문제가 없습니다. Tick()에서 Ticker(), 전역에 이르기까지 이는 JavaScript의 "범위 체인"입니다.

하지만 여전히 문제가 있습니다. 바로 Tick()을 어떻게 호출할 것인가 하는 것입니다. Ticker()의 범위에는 Tick()도 포함됩니다. 두 가지 해결책이 있습니다:

•1) Ticker()의 반환 값으로 n을 증가시키는 메서드를 사용하는 것처럼 반환 값으로 메서드를 호출해야 합니다.
•2) 외부 범위의 변수를 설정합니다. Ticker()에서 했던 것처럼 에 getN을 설정합니다.

코드 복사 코드는 다음과 같습니다.

var getN;
function ticket( config){
var n = config.nStart;
getN = function(){
return n;
};
return function(){
n = config.step;
};
}

var ticker({nStart:100,step:2});
tick();
console.log(getN()) // ->102

참고로 이때 변수 n은 "클로저"에 있어 Ticker() 외부에서 직접 접근할 수는 없지만 두 가지 방법을 통해 관찰하거나 조작할 수 있습니다.

이 섹션의 첫 번째 코드 부분에서는 Ticker() 메서드가 실행된 후 다음에 함수가 호출될 때까지 n 및 Tick()이 소멸되지만 두 번째 코드 부분에서는 Ticker()가 이후에 삭제됩니다. 실행이 완료되면 Tick() 및 getN()이 n에 액세스하거나 변경할 수 있으므로 n은 삭제되지 않으며 브라우저는 n을 유지 관리할 책임이 있습니다. 제가 이해한 "클로저"는 함수 범위 내에 있는 변수 n이 함수 실행 후에도 유지되어야 하고 다른 메서드를 통해 액세스할 수 있는지 확인하는 데 사용되는 메커니즘입니다.

그런데 아직도 뭔가 잘못된 것 같다고요? 동일한 기능을 가진 두 개의 객체인 Ticker1과 Ticker2를 유지해야 하는 경우 어떻게 해야 합니까? 티커()는 하나뿐이라 다시 쓸 수는 없겠죠?

new 연산자와 생성자
new 연산자를 통해 함수를 호출하면 새로운 개체가 생성되고 해당 개체를 사용하여 함수가 호출됩니다. 제가 이해한 바에 따르면, 다음 코드에서 t1과 t2의 구성 과정은 동일합니다.

코드 복사 코드는 다음과 같습니다.

function myClass(){}
var t1 = new myClass();
var t2 = {};
t2.func = myClass;
t2.func();
t2.func = 정의되지 않음;

T1과 t2는 모두 새로 생성된 객체이고 myClass()는 생성자입니다. 마찬가지로,ticker()도 다시 작성할 수 있습니다.

코드 복사 코드는 다음과 같습니다.

function TICKER(config){
var n = config.nStart;
this.getN = function(){
return n;
};
this.tick = function(){
n = config.step;
}
}

varticer1 = new TICKER({nStart:100,step:2});
ticker1.tick();
console.log(ticker1.getN()) // ->102
var ticket2 = new TICKER({nStart:20,step:3});
ticker2.tick();
ticker2.tick();
console.log(ticker2.getN()) ; // ->26

관례에 따라 생성자는 대문자로 표시됩니다. TICKER()는 여전히 순수 객체가 아닌 함수입니다(우리가 "순수"라고 말하는 이유는 함수가 실제로 객체이고 TICKER()가 함수 객체이기 때문입니다). 클로저는 여전히 유효하며 Ticker1에 액세스할 수 없습니다. .N .

프로토타입 프로토타입 및 상속
위의 TICKER()에는 여전히 결함이 있습니다. 즉,ticer1.tick()과ticker2.tick()은 서로 독립적입니다! new 연산자를 사용하여 TICKER()를 호출할 때마다 새 객체가 생성되고 이 새 객체에 바인딩하기 위한 새 함수가 생성됩니다. 새 객체가 생성될 때마다 브라우저는 space.tick() 자체와 변수를 Tick() 내에 저장하는 것은 우리가 기대하는 것과 다릅니다. 우리는 Ticker1.tick과 Ticker2.tick이 동일한 함수 객체를 가리킬 것으로 예상합니다.

이를 위해서는 프로토타입 도입이 필요합니다.

JavaScript에서는 Object 객체를 제외한 다른 객체에는 다른 객체를 가리키는 프로토타입 속성이 있습니다. 이 "다른 객체"는 여전히 프로토타입 객체를 갖고 있으며 최종적으로 Object 객체를 가리키는 프로토타입 체인을 형성합니다. 객체에 대해 메서드를 호출할 때 객체에 지정된 메서드가 없는 것으로 확인되면 Object 객체가 나타날 때까지 프로토타입 체인에서 이 메서드를 검색합니다.

함수도 객체이므로 함수에도 프로토타입 객체가 있습니다. 함수가 선언되면(즉, 함수 객체가 정의되면) 새 객체가 생성되고 이 객체의 프로토타입 속성은 Object 객체를 가리키며 이 객체의 constructor 속성은 함수 객체를 가리킵니다.

생성자를 통해 생성된 새 객체의 프로토타입은 생성자의 프로토타입 객체를 가리킵니다. 따라서 생성자의 프로토타입 객체에 함수를 추가할 수 있으며 이러한 함수는 Ticker1이나 Ticker2에 의존하지 않고 TICKER에 의존합니다.

다음을 수행할 수 있습니다.

코드 복사 코드는 다음과 같습니다.

function TICKER(config){
var n = config.nStart;
}
TICKER.prototype.getN = function{
// 주의: 잘못된 구현
return n;
};
TICKER.prototype.tick = function{
// 주의: 잘못된 구현
n = config.step;
};

이것은 유효하지 않은 구현입니다. 프로토타입 객체의 메서드는 클로저의 내용, 즉 변수 n에 접근할 수 없기 때문입니다. TICK() 메서드가 실행된 후에는 n에 더 이상 액세스할 수 없으며 브라우저는 n을 삭제합니다. 클로저의 콘텐츠에 액세스하려면 객체에 클로저의 콘텐츠에 액세스할 수 있는 몇 가지 간결한 인스턴스 종속 메서드가 있어야 하며 그런 다음 프로토타입에 복잡한 공용 메서드를 정의하여 논리를 구현해야 합니다. 실제로 예제의 Tick() 메서드는 충분히 간결하므로 TICKER에 다시 넣어 보겠습니다. 다음으로 호출자가 Tick()이 호출되는 횟수를 지정할 수 있도록 하는 더 복잡한 메서드인 TickTimes()를 구현합니다.

코드 복사 코드는 다음과 같습니다.

function TICKER(config){
var n = config.nStart;
this.getN = function(){
return n;
};
this.tick = function(){
n = config.step;
} ;
}
TICKER.prototype.tickTimes = function(n){
while(n>0){
this.tick();
n--;
}
};
varticer1 = new TICKER({nStart:100,step:2});
ticker1.tick();
console.log(ticker1.getN()); // - >102
var ticket2 = new TICKER({nStart:20,step:3});
ticker2.tickTimes(2);
console.log(ticker2.getN()); // - >26

이 TICKER는 훌륭합니다. n을 캡슐화하고 객체 외부에서 직접 변경할 수 없으며 복잡한 함수인 TickTimes()가 프로토타입에 정의되어 있습니다. 이 함수는 인스턴스의 작은 함수를 호출하여 객체의 데이터에 대해 작동합니다.

따라서 개체의 캡슐화를 유지하기 위해 제가 제안하는 것은 데이터 작업을 생성자에서 인스턴스 종속(" "비공개"라고도 함)으로 정의된 가능한 가장 작은 단위 함수로 분리하는 것입니다. 프로토타입(예: "공개")에 복잡한 논리를 구현합니다.

마지막으로 상속에 대해 이야기해보겠습니다. 사실, 프로토타입에 함수를 정의할 때 우리는 이미 상속을 사용하고 있습니다! JavaScript의 상속은 C보다 더...음...간단하거나 조잡합니다. C에서는 동물을 표현하기 위해 동물 클래스를 정의하고, 새를 표현하기 위해 동물 클래스를 상속받기 위해 새 클래스를 정의할 수 있지만, 제가 논의하고 싶은 것은 그러한 상속이 아닙니다(이러한 상속은 JavaScript에서도 구현될 수 있지만). ); C에서 상속에 대한 논의는 동물 클래스를 정의한 다음 myAnimal 객체를 인스턴스화하는 것입니다. 예, C에서는 인스턴스화이지만 JavaScript에서는 상속으로 처리됩니다.

JavaScript는 클래스를 지원하지 않습니다. 브라우저는 현재 사용 가능한 객체에만 관심을 갖고 이러한 객체가 어떤 클래스인지, 어떤 구조를 가져야 하는지 걱정하지 않습니다. 이 예에서 TICKER()는 함수 개체입니다. 그러나 현재 new 연산자를 통해 TiCKER1과 Ticker2라는 두 개체가 있으므로 값을 할당하고(TICKER=1) 삭제할 수 있습니다. 호출되면 TICKER()가 생성자 역할을 하고 TICKER.prototype 객체가 클래스 역할을 합니다.

위 내용은 제가 알고 있는 자바스크립트 모듈화 방법입니다. 혹시 초보자이시더라도 도움이 되셨으면 좋겠습니다. 잘못된 부분이 있으면 지적해주세요.

저자: Master Yiyezhai
출처: www.cnblogs.com/yiyezhai

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 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 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

<gum> : Bubble Gum Simulator Infinity- 로얄 키를 얻고 사용하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora : 마녀 트리의 속삭임 - Grappling Hook 잠금 해제 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
Nordhold : Fusion System, 설명
3 몇 주 전 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++ 함수 상속에 대한 자세한 설명: 상속에서 '기본 클래스 포인터'와 '파생 클래스 포인터'를 사용하는 방법은 무엇입니까? May 01, 2024 pm 10:27 PM

함수 상속에서는 "기본 클래스 포인터" 및 "파생 클래스 포인터"를 사용하여 상속 메커니즘을 이해합니다. 기본 클래스 포인터가 파생 클래스 개체를 가리키는 경우 상향 변환이 수행되고 기본 클래스 멤버에만 액세스됩니다. 파생 클래스 포인터가 기본 클래스 개체를 가리키는 경우 하향 캐스팅이 수행되므로(안전하지 않음) 주의해서 사용해야 합니다.

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

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

TrendForce: Nvidia의 Blackwell 플랫폼 제품으로 TSMC의 CoWoS 생산 능력이 올해 150% 증가합니다. TrendForce: Nvidia의 Blackwell 플랫폼 제품으로 TSMC의 CoWoS 생산 능력이 올해 150% 증가합니다. Apr 17, 2024 pm 08:00 PM

4월 17일 이 사이트의 뉴스에 따르면 TrendForce는 최근 Nvidia의 새로운 Blackwell 플랫폼 제품에 대한 수요가 강세를 보이고 있으며, 이로 인해 TSMC의 전체 CoWoS 패키징 생산 능력이 2024년에 150% 이상 증가할 것으로 예상된다는 보고서를 발표했습니다. NVIDIA Blackwell의 새로운 플랫폼 제품에는 B 시리즈 GPU와 NVIDIA 자체 GraceArm CPU를 통합한 GB200 가속기 카드가 포함됩니다. TrendForce는 현재 공급망이 GB200에 대해 매우 낙관적이며, 출하량이 2025년에 100만 개를 초과할 것으로 예상되며 이는 Nvidia 고급 GPU의 40~50%를 차지할 것으로 확인했습니다. 엔비디아는 하반기에 GB200, B100 등의 제품을 출시할 계획이지만, 업스트림 웨이퍼 패키징에는 더욱 복잡한 제품을 채택해야 합니다.

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

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

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

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

C++ 함수 상속에 대한 자세한 설명: 상속 오류를 디버깅하는 방법은 무엇입니까? C++ 함수 상속에 대한 자세한 설명: 상속 오류를 디버깅하는 방법은 무엇입니까? May 02, 2024 am 09:54 AM

상속 오류 디버깅 팁: 올바른 상속 관계를 확인하세요. 디버거를 사용하여 코드를 단계별로 실행하고 변수 값을 검사합니다. 가상 수정자를 올바르게 사용했는지 확인하세요. 숨겨진 상속으로 인해 발생하는 상속 다이아몬드 문제를 살펴봅니다. 추상 클래스에서 구현되지 않은 순수 가상 함수를 확인하세요.

AMD 'Strix Halo' FP11 패키지 크기 노출: Intel LGA1700과 동일, Phoenix보다 60% 더 큼 AMD 'Strix Halo' FP11 패키지 크기 노출: Intel LGA1700과 동일, Phoenix보다 60% 더 큼 Jul 18, 2024 am 02:04 AM

이 웹사이트는 7월 9일에 AMD Zen5 아키텍처 "Strix" 시리즈 프로세서에 두 가지 패키징 솔루션이 있을 것이라고 보고했습니다. 더 작은 StrixPoint는 FP8 패키지를 사용하고 StrixHalo는 FP11 패키지를 사용합니다. 출처: videocardz 출처 @Olrak29_ 최근 밝혀진 바에 따르면 StrixHalo의 FP11 패키지 크기는 37.5mm*45mm(1687제곱밀리미터)로 Intel의 AlderLake 및 RaptorLake CPU의 LGA-1700 패키지 크기와 동일합니다. AMD의 최신 Phoenix APU는 25*40mm 크기의 FP8 패키징 솔루션을 사용합니다. 이는 StrixHalo의 F가

C++ 함수는 코드를 캡슐화하여 GUI 개발 효율성을 어떻게 향상합니까? C++ 함수는 코드를 캡슐화하여 GUI 개발 효율성을 어떻게 향상합니까? Apr 25, 2024 pm 12:27 PM

C++ 함수는 코드를 캡슐화함으로써 GUI 개발 효율성을 향상시킬 수 있습니다. 코드 캡슐화: 함수는 코드를 독립적인 단위로 그룹화하여 코드를 더 쉽게 이해하고 유지 관리할 수 있도록 합니다. 재사용성: 함수는 애플리케이션 전체에서 재사용할 수 있는 공통 기능을 생성하여 중복과 오류를 줄입니다. 간결한 코드: 캡슐화된 코드는 기본 논리를 간결하고 쉽게 읽고 디버깅할 수 있도록 만듭니다.

See all articles