본문 바로가기
javascript

이게 뭐야? JavaScript에서 실행 컨텍스트 이해

by it-square 2021. 12. 29.
반응형

자바스크립트의 실행 컨텍스트를 이해하는 것은 자바스크립트를 배우는 데 있어 가장 중요한 요소 중 하나이다. 실행 컨텍스트의 작동 방식에 대한 확실한 이해 없이 코드를 작성하면 종종 매우 성가시고 추적하기 어려운 버그가 발생한다.

JavaScript를 처음 접하시는 분들은 실행 컨텍스트가 어떻게 작동하는지 시간을 갖고 이해하시기 바랍니다. 그것은 미래에 반드시 성과를 낼 것입니다!

실행 컨텍스트는 또한 이것의 현재 값 또는 함수(또는 메서드)가 실행되는 환경으로 언급된다.

다음은 한 가지 예입니다.

 

출력:

Ralph Asterix is a mechanical engineer. Ralph likes to grow fruits and vegetables in spare time.

7호선부터 8호선까지, 나는 이것을 여러 번 언급한다. 여기서 사용자 오브젝트를 참조하도록 설정됩니다. 그래서 매번 이런 건물에 접근할 때마다 이렇게요예를 들어, 실제로 사용자 오브젝트의 속성 firstName에 액세스하고 있습니다.

하지만 printBio 메소드를 변수에 할당하고 함수로 호출하면 됩니다. 결과는 다르다.

출력:

 
xundefined undefined is undefined. undefined likes to undefined in spare time.

이건 내가 원하던 게 아니야!

함수 호출 방식 때문에 원래 실행 컨텍스트가 손실된 것이다.

실행 컨텍스트를 이해하려면 먼저 글로벌 객체에 대해 논의하는 것이 중요합니다.

 

전역 객체

전역 오브젝트는 JavaScript 스크립트/프로그램이 실행될 때 생성되는 오브젝트입니다. 항상 존재하며 스크립트의 모든 위치에서 액세스할 수 있습니다. 스크립트가 실행 중인 위치에 따라 글로벌 개체는 다음 개체 중 하나로 표시됩니다.

  • 브라우저에서 실행되는 경우 창
  • 노드에서 실행되는 경우 전역
  • WorkerGlobalScope(Worker에서 실행되는 경우)는 조금 더 고급이며 이 문서에서는 다루지 않지만 MDN의 WorkerGlobalScope에 대해 읽어보십시오.

실행 컨텍스트

함수나 메소드를 호출할 때마다 JavaScript는 호출의 실행 컨텍스트를 다른 값으로 명시적으로 설정하지 않는 한 암시적으로 해당 호출의 실행 컨텍스트를 특정 값으로 설정합니다. 실행 컨텍스트가 설정되는 값은 함수 또는 메서드를 호출하는 방법에 따라 달라집니다.

 

Javascript는 항상 실행 컨텍스트를 설정합니다. 당신이 직접 설정해야만 설정이 되지 않습니다.

그러면 자바스크립트는 어떤 값을 참조해야 하는지 어떻게 결정할까요?

정규 함수 호출이 있을 때마다 전역 객체로 설정됩니다. 이 호출이 노드에 있으면 전역 개체가 전역 개체입니다. 만약 그것이 브라우저에서 일어난다면, 그것은 window라고 불리는 객체입니다.

일반 함수 호출이란 무엇입니까?

이것은 단지 다음과 같은 정규 함수 호출이다.

 

여기 3행부터 5행까지 함수 foo를 정의하며, 함수 선언이기 때문에 위의 예에서처럼 정의하기 전에 호출할 수 있다. 리프레셔가 필요할 경우를 대비해서 자바스크립트 기능에 대한 미디엄 기사를 작성한 적이 있는데, 여기 있습니다.

위의 코드는 다음과 같습니다.

Hello [object global]!

브라우저에서 동일한 코드를 실행하면 다음과 같이 출력됩니다.

Hello [object Window]!
 

비정규 함수 호출이란 무엇입니까? 잠시 후에 이것에 대해 다시 설명하겠습니다.

메서드 호출로 작업하는 경우 이 값은 호출 객체로 설정됩니다. 다음은 예입니다.

출력:

Hello World!

위의 예에서 이 값은 호출하는 개체로 설정되며, 이는 foo입니다. 그 결과, 4번째 줄(this.text)의 속성 텍스트에 액세스할 때 실제로 foo.text가 참조하는 값에 액세스합니다. 속성 텍스트에 Hello World! 값이 할당되어 있으므로 console.log(this.text); Hello World!를 콘솔에 출력합니다.

 

내가 전에 "비정규적" 함수 호출에 대해 언급했었어. 제가 말한 내용은 다음과 같습니다.

자바스크립트의 함수들은 일급 객체들이기 때문에 변수들에 할당되고, 다른 함수들에 전달되고, 함수들로부터 반환될 수 있다. 자바스크립트 함수의 이 속성은 실행 컨텍스트가 설정되는 방식을 약간 복잡하게 만든다.

다음은 기능/방법의 원래 실행이 손실되는 몇 가지 시나리오입니다. JavaScript에서 실행 컨텍스트가 결정되는 방식을 이해할 수 있도록 이러한 시나리오를 숙지하는 것이 중요합니다.

변수에 메서드를 할당하고 정규 함수로 호출

우리는 메소드를 호출할 때 이것의 값이 호출 객체라는 것을 알고 있습니다. 그러나 메소드를 복사하여 변수에 할당하면 원래 실행 컨텍스트가 손실되고 새 함수는 전역 개체를 실행 컨텍스트로 가집니다. 다음 예를 들어 다음과 같습니다.

 

출력:

Hello World!

지금까지는 모든 것이 좋습니다.

foo.printText를 복사하여 변수 인쇄에 할당합니다.텍스트 및 인쇄 호출텍스트는 정규 함수입니다.

더 이상 개체를 참조하지 않고 전역 개체를 참조합니다. 따라서 글로벌 개체의 속성 텍스트에 액세스하려고 하면 해당 속성 액세스가 정의되지 않은 것으로 평가됩니다(글로벌 개체 ¯_(ツ)_/¯에 해당 속성이 존재하지 않기 때문입니다). 원래 실행 컨텍스트(개체 foo)가 손실됩니다!

 

이 문제를 어떻게 해결해야 할까요?

실행 컨텍스트를 명시적으로 설정할 수 있습니다. 예를 들어 메소드 바인드를 사용할 수 있습니다. 메서드 바인딩은 제공된 실행 컨텍스트에 영구적으로 바인딩된 새 함수를 반환합니다. 첫 번째 인수는 실행 컨텍스트(참조할 내용)이며, 이후의 인수는 바인드 호출하는 함수/메소드로 전달된다.

해결책은 다음과 같습니다.

출력:

Hello World!
 

8행의 foo.printText.bind(foo)는 실행 컨텍스트로 개체 foo에 영구적으로 바인딩된 완전히 새로운 함수를 반환합니다. 그런 다음 새 기능이 가변 인쇄물에 할당됩니다.다른 함수 이름 또는 식별자와 마찬가지로 해당 함수를 호출하는 데 사용할 수 있는 텍스트입니다(라인 10에서와 다름).

바인드만이 실행 컨텍스트 손실이라는 특정 문제를 해결할 수 있는 유일한 방법은 아니며, 동일한 결과를 얻기 위해 호출이나 신청을 사용할 수도 있습니다.

bind는 인수로 제공된 새 컨텍스트에 영구적으로 바인딩된 완전히 새로운 함수를 반환하는 반면 제공된 컨텍스트로 호출 및 적용 함수 호출에는 중요한 차이가 있습니다.

함수를 다른 함수에 인수로 전달

함수/방법이 원래의 맥락을 잃는 또 다른 흥미로운 시나리오는 우리가 함수를 다른 함수에 인수로서 전달하는 것이다.

 

함수는 다른 함수에 인수로 전달되면 원래 실행 컨텍스트를 잃게 됩니다. 다음은 예입니다.

출력:

undefined

12행에서 printMessage 함수 인수로 method foo.printText를 전달합니다(8~10행에서 정의). 함수 printMessage의 본문에는 코드 줄 하나가 있는데, 이 줄에는 우리가 전달한 함수 호출(라인 9)이 있으며, 이는 궁극적으로 정의되지 않은 출력이다.

이것은 우리가 함수를 다른 함수에 인수로서 전달할 때, 그들은 원래의 실행 컨텍스트를 잃고 대신 그들의 컨텍스트를 전역 객체로 설정하기 때문에 발생한다.

 

다시 말하지만, 이것을 해결하는 방법은 한 가지가 아니다. 이번에는 메소드 콜을 사용하려고 합니다.

printMessage 함수(10줄)에 두 번째 매개 변수인 컨텍스트를 추가했습니다. 새 매개 변수 컨텍스트는 11번째 줄에서 호출 시 foo.printText로 명시적으로 설정하려는 실행 컨텍스트를 나타냅니다. 실제로 foo.printText를 printMessage에 인수로 전달하면 foo.printText가 참조하는 값이 printMessage 함수 정의와 관련하여 로컬 변수로 간주되는 매개 변수 funcArgument에 의해 참조됩니다. 그러므로 funcArgument의 실행 컨텍스트를 11번째 줄에서 호출할 때의 컨텍스트로 설정한다고 해도 과언이 아니다.

비록 우리가 어떤 함수를 인수로 다른 함수에 전달할 때 원래의 실행 컨텍스트가 제거되더라도, 우리는 우리가 원하는 대로 실행 컨텍스트를 설정할 수 있다. 또한 다음과 같이 완전히 다른 개체를 foo.printText의 실행 컨텍스트로 설정할 수 있습니다.

출력:

HELLO WORLD!!!!!!!
 

JavaScript에서 실행 컨텍스트를 이해할 때 기억해야 할 몇 가지 사항:

  • 실행 컨텍스트(이 값)는 정의된 방법에 관계없이 함수 또는 메서드를 호출하는 방법에 따라 달라집니다.
  • 정기적인 함수 호출 시 실행 컨텍스트는 전역 개체로 설정됩니다.
  • 실행 컨텍스트가 메서드 호출을 위해 호출 개체로 설정되었습니다.
  • 바인드, 호출, 적용을 사용하여 실행 컨텍스트를 명시적으로 설정할 수 있습니다.
  • 읽어주셔서 감사합니다.

댓글