인프런 강의 보면서 정리해두기.

눈이 트이는 느낌이다.


Execution context

실행 컨택스트는 코드를 실행하는 데에 필요한 배경이 되는 조건/환경이다.


전역공간 : 자바스크립트가 실행될 때 생성되어 종료될때 종료되어 함수로 볼 수 있음

module : import되는 순간 내부 컨텍스트가 생성되어 모듈코드가 종료될 때 종료되어 함수로 볼 수 있음

결국 실행 컨텍스트는 함수를 실행할때 필요한 조건 또는 환경정보이며,

전역공간, 모듈 또는 함수로 묶인 내부에서는 같은 환경 안에 있는 것이 됨.

if/for/switch/while문은 블록스코프로 let, const에 대해 독립된 공간으로의 역할은 하지만 별도의 실행컨텍스트가 생성되는 것은 아님.


function outer(){
  코드1
  function inner(){
    코드2
  }
  inner();
  코드3
}
outer();
코드4


위 코드는 전역, outer, inner 순으로 컨텍스트가 생성되어(stack),

1, 2, 3, 4 순서로 코드가 실행된다.


call stack

함수의 동작 순서를 제어하는 자료구조

컨텍스트가 전역, outer, inner순으로 쌓인 후 마지막에 들어온 inner부터 실행하여 종료되면 outer, 종료되면 전역 컨텍스트가 실행된다.


환경정보

  • 현재 환경 관련 식별자

VariableEnvironment : 식별자 정보 수집

최초 식별자 정보를 담고 있음.
값에 변화가 생겨도 실시간 반영 안됨.

LexicalEnvironment : 식별자의 데이터 추적

실행컨텍스트를 구성하는 환경정보가 담겨있는 사전처럼 구성한 객체.
값에 변화가 생기면 실시간 반영됨.

  • environmentRecord : 현재 컨텍스트의 내부 식별자 정보

– 호이스팅(hoisting) : 현재 식별자 정보를 environmentRecord에 담는 과정을 이해하기 쉽게 말하는 허구의 개념
식별자 정보를 최상위로 끌어올림 (함수식별자는 함수 그대로 끌어올려짐)

  • outerEnvironmentReference : 현재 문맥에 관련 있는 외부 식별자 정보

– 아까 코드에서 inner의 경우 outerEnvironmentReference는 outer의 LexicalEnvironment를 참조하고, outer는 전역의 LexicalEnvironment에서 참조한다.

– scope chain 현상 : 변수의 유효 범위. outerEnvironmentReference에 의해 만들어짐
가장 가까운 자신부터 점점 멀리 있는 scope로 찾아나가는 것.
inner내부에서는 참조한 outer나 전역에서 선언한 변수를 사용할 수 있지만, outer에서는 inner에서 선언한 변수를 사용할 수 없음.
식별자가 동일한 경우 가장 먼저 찾은 식별자를 사용.


This

실행컨텍스트가 생성될 때 = 함수가 호출될 때 this가 생성된다.

즉, 함수가 어떻게 호출되느냐에 따라서 this가 결정된다.

  • 전역 공간에서 : 최초 this = window(브라우저) / global(node.js)


  • 함수 호출 시 : window / global

함수a를 호출한 대상이 전역객체 이므로 this는 window/global이 됨

function a() {
  console.log(this);
  function b(){
    console.log(this);
  }
  b();  // this = window or global
}
a();  // this = window or global


  • 메서드 호출 시 : 메서드를 호출한 주체
let a = {
  b: function() {
    console.log(this);
  },
}
a.b();  // this = a
a[b]();  // this = a

메서드 : 객체와 관련된 동작을 하게되면 그 객체의 메서드 라고 함

let a = 10;
let obj = {
  a: 20,
  b: function() {
    console.log(this.a);  // 20

    function c() {
      console.log(this.a);  // 10
    }
    c();  // this = window/global

    let self = this;  // 우회법
    function d() {
      console.log(self.a);  //20
    }
    d();  // this = window/global
  },
}
obj.b();  // this = obj

this 변경 : call, apply 등 this 바인딩 명령 사용 or 내부함수 상위에서 this를 별도 변수에 담아서 내부함부에서 사용

arrow function : this를 호출 시 동적으로 바인딩하지 않음. 선언 시 정적으로 결정


  • callback 호출 시 : 기본적으로는 함수 내부에서와 동일

제어권을 가진 함수가 콜백의 this를 지정해둔 경우도 있다.

document.querySelector('a').addEventListener('click', function() {
  console.log(this); // this = DOM Element 'a'
})

this를 지정하고 싶으면 콜백함수 호출할때 bind, call등 사용

함수.call(this로 넘길 객체, 매개변수1, 매개변수2, 매개변수3);
함수.apply(this로 넘길 객체, [매개변수들이 담긴 배열]);

let 변수 = 함수.bind(this로 넘길 객체);
변수(매개변수1, 매개변수2, 매개변수3);
// 아래와 같이도 가능
let 변수 = 함수.bind(this로 넘길 객체, 매개변수1, 매개변수2);
변수(매개변수3);

콜백함수를 호출하는 대상이 지정하는 바에 따라 this 호출


  • 생성자 함수 호출 시 : 인스턴스 객체
function Person(n, a) {
  this.name = n;
  this.age = a;
}
let a = Person('이름', 20); // this = window/global
console.log(window.name, window.age); // 이름, 20

let a = new Person('이름', 20); // this = a
console.log(a.name, a.age); // 이름, 20