keyword
- [ 스코프, 호이스팅, 실행컨텍스트, 클로저 ]
!! 질문 듣고 흐름 생각하기 !!
!! 최대한 두괄식 한 문장으로 시작해보기 !!
질문&답변 & 토의
편하게 생각나는대로~
[Q1. 실행 컨텍스트에는 어떤 정보들이 담겨 있나요?]
- 렉시컬스코프, 변수, 변수객체, this…
- 스코프체인과 렉시컬 스코프의 개념이 약간 혼재되어 있는 것 같다고 느꼈어요
꼬리질문
- 스코프체인의 역할은 무엇인가요?
- 스코프체인 해당 컨텍스트 변수외에 외부함수의 변수에 접근할 수 있도록 하는 역할
- 실행컨텍스트 언제 생성되나요?
- 함수가 호출(실행)될 때!
- 실행컨텍스트 this객체 같이 생성되는데, this에는 어떤 값이 할당되나요? (호출 방식에 따라)
- 일반함수 → 전역
- method 호출 시 → method를 호출한 객체 바인딩
- new 키워드 → 인스턴스
- arrowfunction → this binding x
- call / apply / bind
- call / apply / bind로 지정 가능 (링크)
person2.study.call(person1)
: person2가 가지고 있는 study함수를 person1이 사용할 수 있도록 해라- call / apply
첫번째 인자로 this 지정
- 두번째 인자는 함수호출에 사용할 매개변수를 의미
- call은 매개변수의 값을 각각 받음
- apply는 매개변수를 배열형태로 받음
- 실제 사용할 수 없는 method들 사용가능
- Array.prototype.join.call(arguments)
- 함수의 매개변수인 arguments는 유사배열형태이기 때문에 바로 배열메소드 사용불가 → Array.prototype을 빌려서 배열메소드 사용가능
- bind
- 새롭게 binding된 함수를 만들고 반환
- 반환된 함수에는 this가 바뀌어 있다.
- 따라서 변수에 할당하고, 호출하는 형태로 사용한다.
정리
let student = person2.study.bind(person1);
student()
- 렉시컬 환경 → 선언될 때 만들어지는건지, 실행될 때 생기는건지 (풀리지 않는 의문..)
[Q2. 클로저는 무엇이고, 왜 사용하는지 ]
[Q.클로저는 무엇인가요?]
- 클로저는 외부변수를 기억하고 접근하는 환경을 갖는 함수
- 클로저 정의(외부변수 접근) + 종료된 컨텍스트에 있는 변수에 접근할 수 있는 것.
[Q. 클로저는 왜 사용하나요?]
- 전역 스코프 오염의 방지
- 비공개변수
- 중첩 함수를 통해 특정 정보(외부함수의 변수)를 은닉하고 싶을 때,
- 은닉하고, 특정 함수(클로저함수)로만 변경가능하도록 하는 것
- 커링
꼬리질문
- [ Q. 클로저 사용하신 경험 있나요? ]
- 노션에서 옵저버 패턴, 특정 정보 은닉을 위해 사용? 그럼 왜 사용? 옵저버 패턴에 클로저 어떻게 사용하신가죠?
- useState() → 내부적으로 클로저로 구현, 데이터 변경 방지
useState 사례로 설명할 수 있다면 높은 점수를 얻을 수 있을 것 같다.
- [ Q. 내부 함수는 외부 함수의 변수를 어떻게 참조할 수 있을까요? ]
이
Lexical Envrionment
는 함수가 선언되는 시점에 생성되는 객체이기 때문에, 스코프 체인 역시 생성되었을 때의 환경을 참조하므로 해당 inner function의 outer function을 참조하게 되며, 이는 변하지 않습니다.따라서 내부 함수에서 선언되지 않은 변수를 사용하더라도, 연결된 스코프 체인을 통해 상위 스코프의 Lexical Environment
를 참조하여 선언부가 존재할 경우, 해당 변수를 참조할 수 있게 됩니다.[Q3. TDZ 에 대해서 설명해주세요 ]
- 저는 호이스팅 1줄 설명하고 시작할 듯
Q. [ var, let, const ] 중 어떤 선언 키워드가 TDZ 현상을 발생하게 하는가?
- 참고 링크(https://www.howdy-mj.me/javascript/var-let-const/)
- let과 const 이다.
- var는 선언과 동시에 undefined로 초기화
- let과 const는 선언단계와 초기화 단계가 분리되어 있어요
outfn(){ innerfn(){ // TDZ // TDZ conosole.log(a) -> error // TDZ let a } } var go console.log(go) // undefined
- 변수 선언
- var, let, const라는 변수선언키워드를 통해 js엔진에 알리는 행위다.
- 초기화
- 할당
From GitHub
예상질문 및 답변
1. 실행 컨텍스트는 언제 생성되는가?
우선 코드의 타입에 따라 생성 시점이 달라집니다. 코드 타입은 총 4가지로 구분됩니다.
- 전역코드
- 함수코드
- eval함수
- 모듈코드
- 가장 처음에 전역 실행 컨텍스트가 생성됩니다. 모든 코드는 전역 실행 컨텍스트 안에서 실행됩니다.
- 함수가 호출되면 함수 내부의 함수 코드가 평가되고 함수 실행컨텍스트가 생성됩니다.
- 빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드는 함수내부에 실행컨텍스트를 생성합니다.
- 모듈 내부에 존재하는 소스코드가 평가될 때 모듈 실행컨텍스트가 생성됩니다.
실행 컨텍스트는 어떤 정보가 담겨 있는가?
- 식별자 정보와 식별자에 바인딩 된 값
식별자란?
- 변수, 함수, 클래스 등의 이름을 모두 식별자라고 한다. 예를 들어
let x
,var y
,function z()
에서 x, y, z를 '식별자'라고 한다.
식별자에 바인딩 된 값이란?
- 자바스크립트 엔진은 코드를 실행하기 앞서 코드를 평가하면서 식별자를 실행컨텍스트의 렉시컬환경에서 key-value 형태로 관리한다. 이 때 key를 식별자, value를 식별자에 바인딩 된 값이라고 한다.
왜 식별자에 값이 "바인딩" 되었다고 표현하는지?
- 어떤 키워드로 선언하였냐에 따라서 "선언"단계와 "초기화"단계가 분리되거나 동시에 일어난다. var로 선언한 키워드는 "선언"단계와 "초기화" 단계가 동시에 이루어지고 암묵적으로 undefined로 할당이 된다. 이런 과정을 식별자에 값이 바인딩이 되었다라고 할 수 있고 이 과정이 호이스팅이 발생하게 되는 이유이다. 이후 런타임에 할당문을 만나면 다시 값이 할당이 되는데, 식별자에 값이 다시 바인딩이 된 것이라 할 수 있다.
- 식별자 스코프
- 실행컨텍스트는 렉시컬 환경이라는 자료구조를 가지고 있고, 렉시컬 환경에 "상위 스코프"에 대한 정보가 담겨있다.
- 코드 실행 순서
- 실행컨텍스트는 실행컨텍스트 스택이라는 자료구조를 가지고 있고, 실행컨텍스트 스택을 통해 코드 실행 순서를 관리한다.
- this 바인딩
- this 바인딩은 코드가 평가되어 실행 컨텍스트가 생성된 이후에, 런타임에서 함수의 호출 방식에 따라 결정된다. this바인딩에 대한 정보도 실행 컨텍스트 안에서 관리된다.
실행 컨텍스트를 아는 것은 왜 중요한가?
실행 컨텍스트는 자바스크립트의 핵심 개념, 실행 컨텍스트를 이해하면 자바스크립트가 스코프를 기반으로 식별자와 식별자에 바인딩된 값을 관리하는 방식과 호이스팅이 발생하는 이유, 클로저의 동작 방식, 그리고 태스크 큐와 함께 동작하는 이벤트 핸들러와 비동기 처리의 동작 방식을 이해할 수 있다.
렉시컬 환경은 무엇인가?
실행컨텍스트는 식별자와 스코프를 관리하기 위해 렉시컬 환경이라는 영역을 가지고 있다. LexicalEnvironment은 식별자에 대한 정보를 관리하는 환경레코드 컴포넌트, 상위 스코프를 가리키는 외부 렉시컬 환경에 대한 참조 컴포넌트 2가지로 구성되어 있다.
클로저와 실행 컨텍스트는 어떤 관계가 있는가?
함수가 호출되면 함수가 평가되며 이 때 함수 실행 컨텍스트가 생성된다. 그리고 함수가 종료되었을 때, 실행 컨텍스트 스택에서 함수 실행컨텍스트는 사라졌지만 렉시컬 환경에 대한 객체는 즉시 사라지지 않는다. 만약 어떤 객체가 이 렉시컬 환경을 참조하고 있다면 이 렉시컬 환경은 계속 존재하며 이를 클로저라 한다. (아무도 참조하지 않는다면 가비지 컬렉터에 의해 메모리 상에서 제거된다)
스코프 체인은 무엇인가?
현재 실행중인 실행컨텍스트의 스코프에서 찾는 값이 없을 때 상위 스코프로 올라가서 찾는 방식.
참고
모던 자바스크립트 딥 다이브 23장 실행 컨텍스트