23장 실행 컨텍스트
실행 컨텍스트
•
자바스크립트의 동작 원리를 담고 있는 핵심개념
실행 컨텍스트를 바르게 이해하면?
소스코드
•
타입
전역 코드(global code) | 전역에 존재하는 소스코드.
전역에 정의된 함수, 클래스 등의 내부 코드는 포함되지 않는다. |
함수 코드(function code) | 함수 내부에 존재하는 소스코드.
함수 내부에 중첩된 함수, 클래스 등의 내부 코드는 포함되지 않는다. |
eval 코드(eval code) | 빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드. |
모듈 코드(module code) | 모듈 내부에 존재하는 소스코드.
모듈 내부의 함수, 클래스 등의 내부 코드는 포함되지 않는다. |
타입을 4가지로 구분하는 이유?
•
타입 에 따라 실행 컨텍스트를 생성하는 과정과 관리 내용이 다르기 때문!
•
소스코드 평가
◦
실행 컨텍스트를 생성.
◦
변수, 함수 등의 선언문만 먼저 실행.
◦
생성된 변수나 함수 식별자를 키(key)로 실행 컨텍스가 관리하는 스코프 에 등록.
(호이스팅?)
•
소스코드 실행
◦
평가 과정이 끝나야 비로소 소스코드가 순차적으로 실행됨.
◦
소스코드의 실행에 필요한 정보, 즉 변수나 함수의 참조를 실행 컨텍스트가 관리하는 스코에서 검색해서 취득함.
◦
변수 값의 변경, 할당 등의 실행 결과는 다시 실행 컨텍스트가 관리하는 스코프에 등록.
실행 컨텍스트의 역할
1.
선언에 의해 생성된 모든 식별자를 스코프를 구분하여 등록하고 상태 변화를 지속적으로 관리.
2.
스코프 체인을 형성해 상위 스코프로 이동하여 식별자 검색 가능
3.
현재 실행 중인 코드의 순서를 변경하거나 다시 되돌아갈 수 있게 함.
→ 실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다!
실행 컨텍스트 스택
•
콜 스택(call stack) 이라고 부르기도 한다.
•
코드의 실행 순서를 관리함.
•
스택의 최상위는 언제나 현재 실행 중인 코드의 실행 컨텍스트다.
→ 실행 중인 실행 컨텍스트(running execution context)
스택 구조
렉시컬 환경(Lexical Environment)
•
식별자와 식별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조.
•
실행 컨텍스트를 구성하는 컴포넌트.
•
스택이 실행 순서를 관리한다면, 렉시컬 환경은 스코프와 식별자를 관리한다.
렉시컬 환경의 구성 컴포넌트
24장 클로저
정의
•
클로저는 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서 사용되는 중요한 특성.
•
MDN에서 정의한 클로저는 다음과 같다.
•
외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이러한 중첩 함수를 클로저라고 부른다.
•
예제
const x = 1;
function outerFunc() {
const x = 10;
// outerFunc() 함수 내부에서 innerFunc() 중첩 함수 정의
function innerFunc() {
console.log(x); // 10
}
// innerFunc() 호출. 이때, innerFunc의 상위 스코프는 외부함수 outerFunc의 스코프.
// 따라서 innerFunc 내부에서 자신을 포함하고 있는 outerFunc의 x 변수에 접근할 수 있다.
innerFunc();
}
outerFunc();
JavaScript
복사
렉시컬 스코프
•
클로저 특성이 나타나는 이유는 자바스크립트가 렉시컬 스코프를 따르는 프로그래밍 언어이기 때문!
•
함수를 어디서 호출했는지가 아니라, 함수를 어디에 정의했는지에 따라 상위 스코프를 결정.
→ 렉시컬 환경의 “외부 렉시컬 환경에 대한 참조”에 저장할 참조값, 즉 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)에 의해 결정된다. 이것이 렉시컬 스코프다!
[[Environment]]
•
함수는 자신의 내부 슬롯인 [[Environment]] 에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장한다.
const x = 1;
function foo() {
const x = 10;
// 상위 스코프는 함수 정의 환경(위치)에 따라 결정된다.
// 함수 호출 위치와 상위 스코프는 아무런 관계가 없다.
bar();
}
// 함수 bar()는 자신의 상위 스코프, 즉 전역 렉시컬 환경을 [[Environment]]에 저장하여 기억한다.
function bar() {
console.log(x);
}
foo(); // ?
bar(); // ?
JavaScript
복사
25장 클래스
클래스
구조
// 클래스 선언문
class Person {
// 생성자
constructor(name) {
// 인스턴스 생성 및 초기화
this.name = name; // name 프로퍼티는 public하다.
}
// 프로토타입 메서드
sayHi() {
console.log(`Hi! My name is ${this.name}`);
}
// 정적 메서드 : 클래스의 인스턴스 없이 호출할 수 있는 함수.
// 클래스가 인스턴스화 되면 호출할 수 없다.
static sayHello() {
console.log('Hello!');
}
}
// 인스턴스 생성
const me = new Person('subin');
// 인스턴스의 프로퍼티 참조
console.log(me.name); // subin
// 프로토타입 메서드 호출
me.sayHi(); // 'Hi! My name is subin'
// 정적 메서드 호출
Person.sayHello(); // Hello;
JavaScript
복사
인스턴스 생성
•
클래스는 생성자 함수이며, new 연산자와 함께 호출하여 인스턴스를 생성한다.
•
클래스는 인스턴스 생성만이 목적이므로, 반드시 new 연산자와 함께 호출되어야 한다.
메서드
•
constructor(생성자)
◦
인스턴스를 생성하고 초기화하기 위한 특수한 메서드.
◦
이름을 변경할 수 없다.
◦
별도의 반환문 return 을 가지지 않는다.
◦
new 연산자와 함께 호출되면, 생성자 함수와 동일하게 암묵적으로 this를 반환한다.
◦
생략할 수 있다. 생략하면 빈 객체를 생성한다.
•
Prototype Method
◦
생성자 함수와는 다르게, prototype propety 에 메서드를 추가하지 않아도 기본적으로 프로토타입 메서드가 된다.
◦
클래스가 생성한 인스턴스의 프로토타입 체인의 일원이 된다.
•
Static Method
◦
인스턴스를 생성하지 않아도 호출할 수 있는 메서드.
◦
메서드에 static 키워드를 붙이면 정적 메서드가 된다.
클래스에서 정의한 메서드의 특징
상속에 의한 클래스 확장
•
기존 클래스를 상속받아 새로운 클래스를 확장extend 하여 정의하는 것.
•
super 를 호출하면 수퍼클래스의 constructor 를 호출한다.
•
메서드 내에서 super 를 참조하면 수퍼클래스의 메서드를 참조할 수 있다.
// 수퍼(베이스/부모) 클래스
class Parent {
constructor(a, b) {
this.a = a;
this.b = b;
}
sayHi() {
return 'Hi!'
}
}
// 서브(파생/자식) 클래스
class Child extends Parent {
constructor(a, b, c) {
super(a, b);
this.c = c;
}
sayHi() {
// super.sayHi는 수퍼클래스의 프로토타입 메서드를 가진다.
return `${super.sayHi()} How are you?` // Hi! How are you?
}
}
JavaScript
복사