3주차 시험 개념정리

짧은 개념 정리글


실행 컨텍스트

식별자, 스코프, 호이스팅, 클로저 등의 동작원리를 담고 있는 자바스크립트의 핵심개념.
실행 가능한 코드를 평가하고 실행하기 위해 필요한 환경을 제공하고 코드의 실행결과를 실제로 관리하는 영역.


실행 컨텍스트 등록 과정

코드의 평가 과정에서 실행 컨텍스트가 생성되고 변수, 함수, 클래스 등의 선언문이 평가되어 그 결과가 실행 컨텍스트에 등록 -> 코드 평가 과정 끝 -> 선언문을 제외한 코드 순차적으로 실행


실행 컨텍스트 스택

코드의 실행 순서를 스택형태의 자료구조로 관리. ( = 콜스택)


렉시컬 환경

스코프와 식별자를 관리. 스코프를 구분하여 식별자를 등록하고 관리하는 저장소 역할을 한다.


렉시컬 환경의 3가지 콤퍼넌트

  1. 환경레코드
  2. 외부렉시컬환경참조
  3. ThisBinding

실행 컨텍스트의 생성과 식별자 검색 과정

  1. 전역 객체 생성 (코드가 평가 되기 이전에 생성된다.)

  2. 전역 코드 평가

    1. 전역 실행 컨텍스트 생성
  3. 전역 렉시컬 환경 생성

    1. 객체 환경 레코드 생성
      1. 선언적 환경 레코드 생성
    2. 외부 렉시컬 환경에 대한 참조 할당
  4. this 바인딩

  5. 함수 호출

    1. 함수 실행 컨텍스트 생성
    2. 함수 렉시컬 환경 생성
      1. 함수 환경 레코드 생성
    3. 외부 렉시컬 환경에 대한 참조 할당
    4. this 바인딩

식별자를 검색할 때는 실행 중인 실행 컨텍스트의 렉시컬 환경에서 식별자를 검색한다.


클로저

​ 함수와 그 함수가 선언된 렉시컬 환경(Lexical environment)과의 조합이다.


함수 객체의 내부 슬롯 [[Environment]]

​ 함수는 자신의 내부 슬롯[[Environment]]에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장한다.


클로저의 역할

  1. 상태를 안전하게 유지하기 위해 사용.
  2. 의도치 않게 변경되지 않도록 안전하게 은닉.
    1. 상태가 변경되면 최신 상태(state)를 유지.

아래는 왜 클로저가 아닌가?

함수 makeCounter를 호출해 함수를 반환할 때 반환된 함수는 자신만의 독립된 렉시컬 환경을 갖는다

문제는 2개의 makeCounter를 호출 했으므로 각각의 렉시컬환경에 counter라는 변수를 전부 가지고 있으므로 counter는 증감 되지 않는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 함수를 인수로 전달받고 함수를 반환하는 고차 함수
// 이 함수가 반환하는 함수는 카운트 상태를 유지하기 위한 자유 변수 counter을 기억하는 클로저다.
function makeCounter(predicate) {
// 카운트 상태를 유지하기 위한 자유 변수
let counter = 0;

// 클로저를 반환
return function () {
// 인수로 전달 받은 보조 함수에 상태 변경을 위임한다.
counter = predicate(counter);
return counter;
};
}

// 보조 함수
function increase(n) {
return ++n;
}

// 보조 함수
function decrease(n) {
return --n;
}

// 함수로 함수를 생성한다.
// makeCounter 함수는 보조 함수를 인수로 전달받아 함수를 반환한다
const increaser = makeCounter(increase); // ①
console.log(increaser()); // 1
console.log(increaser()); // 2

// increaser 함수와는 별개의 독립된 렉시컬 환경을 갖기 때문에 카운터 상태가 연동하지 않는다.
const decreaser = makeCounter(decrease); // ②
console.log(decreaser()); // -1
console.log(decreaser()); // -2
img

클로저를 사용시 나타나는 실수

1
2
3
4
5
6
7
8
9
10
11
var arr = [];

for (var i = 0; i < 5; i++) {
arr[i] = function () { // ①
return i;
};
}

for (var j = 0; j < arr.length; j++) {
console.log(arr[j]()); // ②
}

출력시 i가 게속 5로만 출력된다. i를 var키워드로 선언했고 따라서 i는 전역 렉시컬 환경의 window의 소유이기 때문이다.

arr함수 호출이 2번째 for문 때 일어나기 때문에 그 때 실행컨텍스트가 쌓이고 i를 반환한다.

그 때의 i는 값이 5다. 따라서 5를 5번 출력한다.


해결법 1 - 즉시 실행 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
var arr = [];

for (var i = 0; i < 5; i++){
arr[i] = (function (id) { // ①
return function () {
return id;
};
}(i));
}

for (var j = 0; j < arr.length; j++) {
console.log(arr[j]());
}

즉시 실행 함수의 매개변수 id는 반환한 함수의 상위 스코프(즉시 실행 함수)에 존재하기 때문에 자유변수가 된다.

즉시 실행 함수가 반환한 함수에 의해 그 값이 유지된다.


해결법 2 - let 키워드 사용

1
2
3
4
5
6
7
8
9
const arr = [];

for (let i = 0; i < 3; i++) {
arr[i] = () => i;
}

for (let i = 0; i < arr.length; i++) {
console.log(arr[i]()); // 0 1 2
}

for 문이 반복될 때마다 독립적인 렉시컬 환경을 생성하여 식별자의 값을 유지한다.


자바스크립트의 클래스

함수. 객체를 만드는 용도.


클래스 vs 생성자함수

  1. 클래스는 new 연산자 없이 호출 시 에러를 발생한다.
  2. 상속을 지원하는 extends 키워드 와 super키워드 제공
  3. 클래스는 호이스팅이 발생하지 않는 것처럼 동작함( 마치 let, const )
  4. 암묵적으로 strict모드로 실행됨(해지 불가)
  5. 클래스의 메소드들은 모두 열거되지 않는다.

클래스는 문법적 설탕이 아닌 이유

​ 생성자 함수를 기반으로 한 객체 생성방식보다 견고하면서 명료하기 때문에 새로운 객체 생성 메카니즘이다.


클래스의 메소드 3가지

  1. 정적 메소드 ( static sayHello( ) { } )
  2. 프로토타입 메소드 ( sayHello( ) { } )
  3. constructor 메소드 ( constructor( ) { } )

클래스에서 정의한 메소드의 특징

  1. 메소드 축약 표현을 이용
  2. 콤마가 필요없다.
  3. 암묵적인 strict모드
  4. 열거 불가능
  5. new연산자와 함께 호출이 불가능.

클래스 인스턴스 생성 과정

  1. 인스턴스 생성 (빈 객체)
  2. 해당 인스턴스의 prototype 객체가 설정됨.
  3. 인스턴스를 this에 암묵적으로 바인딩 ( constructor 내부의 this는 클래스가 생성한 인스턴스를 가리킴. )
  4. 인스턴스 초기화 (프로퍼티 추가)
  5. 프로토 타입 / 정적 메소드 추가
  6. 인스턴스 반환

클래스 private 필드

1
2
3
4
5
6
class Person {
// private 필드 정의
#_name = '';
}

const person = new Person();

person.#_name을 참조하면 private 관련 에러를 발생하고, person._name을 참조하면 undefined를 반환한다.


extends

부모 클래스를 자식 클래스에 상속하는 키워드


super

수퍼클래스의 constructor를 호출.

super를 참조하여 수퍼클래스의 메소드를 호출.

constructor를 기재시 반드시 counstructor 내부 최상단에 작성해야됨.

constructor를 기재하고 super를 안적거나 최상단에 미기재시 에러 발생. (constructor를 미기재했다면 암묵적으로 전달함)

서브 클래스의 constructor 에서만 호출.


상속 클래스의 인스턴스 생성과정

  1. 서브클래스의 super 호출 - 내부 슬롯 [[ConstructorKind]] (‘base’, ‘derived’) = ‘derived’
  2. 인스턴스 생성(빈객체)을 수퍼클래스에게 위임.
  3. 수퍼클래스 인스턴스 생성 및 this 바인딩
  4. 수퍼클래스의 인스턴스 초기화
  5. 수퍼클래스의 프로토타입 / 정적 메소드 추가
  6. 서브 클래스 constructor로의 복귀 및 this 바인딩
  7. 서브 클래스 인스턴스 초기화
  8. 인스턴스 반환

Share