Computer >> 컴퓨터 >  >> 프로그램 작성 >> JavaScript

웹 기초:범위 및 JavaScript 폐쇄 – 입문서

자바스크립트 언어에서 가장 큰 유행어 중 하나는 폐쇄입니다. FAANG 회사에서 많은 면접 질문의 주제입니다. 이 기사에서는 클로저와 범위에 대해 이야기하고 간단한 예를 통해 개념을 설명한 다음 더 큰 기술 대기업 중 한 곳과의 인터뷰에서 나온 샘플 질문으로 마무리합니다.

범위

누군가가 프로젝트의 범위에 포함되거나 포함되지 않는 항목을 알려준다면 그것은 무엇을 의미합니까?

이에 대한 답을 생각하면 잠망경이나 망원경을 떠올리고 싶다. 이 도구는 렌즈의 범위 내에서 모든 종류의 사물을 보여줍니다. 범위 안에 있습니다. . 범위를 벗어난 경우 , 당신은 렌즈의 직경을 넘어서 볼 수 없습니다. 그리고 지름을 벗어난 물체에 빛을 비추는 것은 불가능합니다. JavaScript에서 매우 중요하고 구별되는 세 가지 유형의 범위(로컬, 전역 및 어휘)에 대해 이야기할 때 이에 대해 생각해야 합니다.

로컬 범위

로컬 스코프는 오늘 이야기할 3가지 스코프 중 가장 작은 스코프입니다. 함수를 선언할 때 대괄호({}) 안의 모든 항목은 함수에 대해 로컬인 것으로 간주됩니다. JavaScript 엔진이 함수를 읽을 때 변수를 선언합니다. 끝날 때 변수를 파괴합니다.

function greeting() {
 var websiteName = 'Career Karma';
 return `Hello ${websiteName}`;
}
 
console.log(greeting()); // Hello Career Karma
console.log(websiteName); // ReferenceError: websiteName is not defined

보시다시피 호출된 인사말 함수의 결과를 "console.log()"하면 함수가 실행된 후 websiteName에 액세스할 수 있습니다. 이것은 우리가 찾던 'Hello Career Karma' 문자열을 제공합니다. console.log() 함수 내에서 선언된 변수의 정의되지 않았기 때문에 오류가 발생합니다.

이미 언급했듯이 websiteName이 정의되지 않은 이유는 변수가 호출될 때 함수 내부에서 생성되고 터미널 문이 실행될 때 소멸되기 때문입니다. 특별한 설정이 없는 한 함수 외부의 모든 항목은 함수 내부의 항목에 액세스할 수 없습니다.

글로벌 범위

이 다음 범위는 이 문구를 문자 그대로 번역한 것입니다. 전역 범위는 함수 외부에서 선언된 항목을 가져 와서 모든 스크립트와 메서드 및 함수가 논리에 액세스하고 사용할 수 있는 공간에 예약합니다.

 
let counter = 0; // global -- declared outside function
 
const add = () => { // function declaration
   let counter = 0; // local -- declared inside function
   counter += 1; 
   // counter increased by 1 -- which counter variable increased?
   return counter;
}
 
add(); // invoke
add(); //  three
add(); //  times
console.log(counter) // is this 3 or 0? Why? 

위의 코드는 console.log() 코드 끝에 있는 카운터? 어떤 일이 일어날 것으로 예상하십니까?

참가자의 81%는 부트캠프에 참석한 후 기술 직업 전망에 대해 더 자신감을 느꼈다고 말했습니다. 지금 부트캠프에 참여하십시오.

부트캠프 졸업생은 부트캠프 시작부터 첫 직장을 찾는 데까지 6개월도 채 걸리지 않았습니다.

코드를 살펴보겠습니다.

  1. 글로벌 환경에서 선언되고 시작된 카운터 변수입니다.
  2. 글로벌 환경에서 선언된 함수를 추가합니다.
  3. 추가가 호출됩니다.
  4. 로컬 환경에서 선언되고 시작된 카운터 변수.
  5. 로컬 카운터가 1 증가 ⇐ 왜 글로벌이 아닌 로컬인가요?
  6. 카운터가 반환됩니다. 기능이 종료됩니다.
  7. 추가가 다시 호출됨
  8. 4~6단계를 다시 수행합니다.
  9. 3~6단계를 다시 반복합니다.
  10. console.log(counter); ⇐ 무엇을 반환합니까?

카운터가 매번 1일 때 함수가 종료되기 때문에 로컬 카운터 변수는 함수가 실행될 때마다 다시 선언되고 0에서 다시 시작됩니다. 무슨 일이 일어나든 카운터는 항상 로컬 수준에서 1에서 멈춥니다.

함수가 범위 내에서 변수를 찾으면 변수에 대한 전역 범위를 찾지 않으므로 전역 변수가 변경되지 않습니다. 따라서 console.log() 해당 문의 환경 내에서 가장 가까운 정의된 변수가 전역 환경에 있으므로 0을 출력합니다.

어휘 범위

어휘 범위는 JavaScript에서 가장 기본적인 개념 중 하나입니다. 함수나 변수의 생성은 코드의 특정 부분에 액세스할 수 있고 코드의 다른 부분에는 액세스할 수 없다는 아이디어입니다. 그것은 모두 각 변수와 함수의 선언이 어디에 있는지에 달려 있습니다.

이 코드 블록을 살펴보겠습니다.

const init = () => { // <== This is our outer function
 const var1 = 'Career'; // outer scope
 const second = () => { // <== This is our inner function
   const var2 = 'Karma'; // inner scope
   console.log(var1); // Career
   console.log(var2); // Karma
   return var1 + " " + var2;
 };
 
 // console.log(var2); // undefined
 
 
 return second();
};
init();
 

여기에 중첩된 함수 집합이 있습니다. init() 함수는 var1이라는 변수를 선언하고 second라는 함수를 선언하고 second()를 호출합니다. .

컴파일러가 이 코드를 처음 통과할 때 우리가 가지고 있는 것을 높은 수준에서 살펴봅니다.

  1. init() 기능
  2. init() 호출

이 시점에서 우리는 init() 함수 내부에서 다른 것을 볼 수 없습니다. 우리는 함수가 존재한다는 것만 알고 있습니다. init() 함수가 호출되면 컴파일러는 함수 내부에 있는 또 다른 높은 수준을 살펴봅니다.

  1. var1
  2. second() 기능
  3. second() 호출

init() 함수는 second() 내부에서 무슨 일이 일어나는지 전혀 알지 못합니다. 차단하다. 어휘 환경에 있는 내용만 볼 수 있습니다. – 주변 상태.

각 중첩 함수는 러시아 마트료시카 중첩 인형 세트와 같은 더 작은 컨테이너에 있습니다(예를 들어 무엇인지 확실하지 않은 경우 페이지 상단 참조). 인형은 컨테이너 내부에서 무슨 일이 일어나고 있는지, 부모에서 이미 발생했거나 선언/읽은 것에 대해서만 알고 있습니다. 예를 들어 가장 큰 인형은 컨테이너에 다음 인형이 있다는 것만 압니다. 세트의 다른 인형에 대해서는 알지 못하며 어휘 환경(상태)과 이미 일어난 일(외부 범위)만 알 수 있습니다.

본질적으로 우리는 두 가지를 알고 있습니다.

  1. 외부 범위는 내부 범위를 볼 수 없습니다.
  2. 내부 범위는 외부 범위에 액세스할 수 있습니다.

외부 대응은 내부 범위에서 무슨 일이 일어나고 있는지 볼 수 없기 때문에 이것이 단방향 관계라고 안전하게 말할 수 있습니다. 내부는 외부 범위에서 변수를 보고 사용할 수 있지만 외부는 내부를 볼 수 없습니다. 이를 어휘 범위라고 합니다. .

어휘 범위 지정의 장점은 변수 값이 코드에서의 위치에 따라 결정된다는 것입니다. 함수는 먼저 로컬 환경 내에서 변수의 의미를 찾습니다. 찾을 수 없으면 해당 함수를 정의한 함수로 이동합니다. 거기에서 찾을 수 없으면 체인을 위로 이동하여 다음 정의된 함수로 이동합니다.

이것은 JavaScript에서 매우 중요한 개념이 되어 JavaScript 프레임워크와 그 작동 방식에 대해 더 많이 배울 때 자주 등장하게 될 것입니다. 외부에서 아래로 전달할 수 있지만 다른 방향으로 "위"로 전달할 수는 없습니다. 이것은 우리가 당면한 주요 주제인 종료에 도달할 때 매우 중요합니다. .

폐쇄

클로저의 정의는 어휘 범위의 정의와 매우 유사합니다. 둘의 주요 차이점은 클로저는 고차 함수이고 어휘 범위는 그렇지 않다는 것입니다. 고차 함수에는 한 가지 기본 특성이 있습니다. 즉, 함수를 반환하거나 함수를 매개변수로 사용합니다.

Closure는 해당 함수가 나중에 호출되는 경우에도 어휘 범위에 액세스할 수 있는 함수입니다.

클로저와 렉시컬 스코프는 모두 고유한 변수를 가지고 있고, 부모 함수의 변수와 매개변수에 접근할 수 있고, 전역 변수를 사용할 수 있습니다. 다음 코드를 살펴보겠습니다.

function greeting() { //outer scope (parent function)
 const userName = "CrrKrma1952"; // parent variable
 function welcomeGreeting() { // inner function
   console.log("Hello, " + userName); // accesses parent var
   return "Hello, " + userName; // terminal statement
 }
 return welcomeGreeting; // returns a function (which makes it HOF)
} // end of greeting()
 
const greetUser = greeting(); //
greetUser(); //  Hello, CrrKrma1952
  1. greeting() 기능은 있지만 아직 내용을 모릅니다.
  2. greetUser 존재하지만 아직 내용을 모릅니다
  3. greetUser() – 이것은 이전 라인을 호출하고, 이는 차례로 Greeting() 함수를 호출합니다.
  4. 사용자 이름 선언
  5. welcomeGreeting() 존재하지만 아직 내용을 모릅니다
  6. welcomeGreeting() 아래의 반환 문 블록은 동일한 기능을 반환합니다.
  7. console.log(‘Hello, ‘ + userName); 여기의 console.log는 상위 범위에 액세스하여 userName의 값을 가져올 수 있습니다.
  8. 함수를 종료하고 코드 블록 내 변수의 의미를 파괴하는 터미널 문입니다.

이 코드에서는 나중에 상위 범위에 액세스할 수 있도록 함수를 중첩하여 정보를 전달합니다.



결론

이 기사에서 우리는 꽤 무거운 JavaScript 주제인 범위와 클로저에 대해 이야기했습니다. 나는 분기하여 주제에 대한 여러 다른 기사를 읽는 것이 좋습니다. 이것을 가르치는 방법은 다양한 관점에서 올 수 있습니다. 즉, 물론 그것을 배우는 방법은 많습니다. 이 입문서가 도움이 되었기를 바랍니다! 폐쇄에 대한 연구를 계속하는 데 행운을 빕니다!