Node.js - 자바스크립트 실행 컨텍스트

lano·2022년 6월 13일
0

nodejs

목록 보기
5/7

1. 실행 컨텍스트란?

실행 컨텍스트는 자바스크립트 코드가 실행되는 환경이다.
코드에서 참조하는 변수, 객체(함수 포함), this등에 대한 레퍼런스가 있다.
실행 컨텍스트는 전역에서 시작해, 함수가 호출될 때 스택에 쌓이게 된다.
중요한 점은 실행 컨텍스트에 이름에 맞게 함수가 실행이 될 때 문맥이 만들어 진다.

2. practice - 실행 컨텍스트 작성

let a = 10;
function f1() {
    let b = 20
    function print(v) { console.log(v) }
    function f2() {
        let c = 30
        print(a + b + c)
    }
    f2();
}
f1();

step1. 전역

'전역 컨텍스트': {
  '변수 객체': {
    arguments: null,
    variable: [ { 'a': 10 }, { 'f1': function } ]
  },
  scopeChain: ['전역 변수 객체'],
  this: window
}
  • 변수가 변수 객체에 변수와 할당된 값이 들어간다.
  • 함수 선언식의 경우 선언과 동시에 변수 객체에 변수로 집어 넣어지고 동시에 함수 정의 내용도 할당된다.
  • 함수 표현식의 경우에는 변수 객체에 변수로 집어 넣어지고 동시에 함수 정의 내용이 할당된다.
  • 그래서 선언식의 경우에는 호출문이 먼저있고 함수가 나중에 있어도 함수가 정상 작동하지만 표현식은 컨텍스트 상 변수는 있지만 내용이 할당되기 전이라 호출문이 먼저 있다면 에러가 발생한다.

step2. f1() 호출

'f1 컨텍스트': {
  '변수 객체': {
    arguments: null,
    variable: [ { 'b': 20 }, { 'print': function }, { 'f2': function } ]
  },
  scopeChain: ['전역 변수 객체', 'f1변수 객체'],
  this: window
}

step3. f2() 호출

'f2 컨텍스트': {
  '변수 객체': {
    arguments: null,
    variable: [ { 'c': 30 } ]
  },
  scopeChain: ['전역 변수 객체', 'f1변수 객체', 'f2변수 객체'],
  this: window
}

step4. print(a + b + c) 호출

'print 컨텍스트': {
  '변수 객체': {
    arguments: [{ v: 60 }],
    variable: null
  },
  scopeChain: ['전역 변수 객체', 'f1변수 객체', 'f2변수 객체', 'print변수 객체'],
  this: window
}
  • print(a + b + c) 호출 될때 실행 컨텍스트가 생성이된다.
  • 이때 a, b, c는 스코프 체인을따라 각각의 변수들을 찾아서 대입시킨다.

3.this를 결정 짓는 방법 - this는 함수가 실행될 때 결정이된다.

const obj = {
    name: "seo",
    sayName: function() {
        console.log("sayName: ", this);
        function inner1() {
            console.log("inner1: ", this);
        }
        const inner2 = () => {
            console.log("inner2: ", this);
        }
        function bindedInner() {
            console.log("bindedInner: ", this)
        }
        inner1();
        inner2();
        bindedInner.bind(obj)();
    },
    sayName2: () => {
        console.log("sayName2: ", this);
        function inner3() {
            console.log("inner3: ", this);
        }        
        const inner4 = () => {
            console.log("inner4: ", this);
        }
        inner3();
        inner4();
    }
}
obj.sayName();
obj.sayName2();
const sayN = obj.sayName;
const sayN2 = obj.sayName2;
sayN();
sayN2();

callstack - (설명의 편의를 위해 함수가 끝난후 스택을 지우지는 않았음)

inner4() -> this: window(화살표 함수 이므로 부모인 sayN2의 this)
inner3() -> this: window
sayN2() -> this: window
bindedInner() -> this: obj(일반함수에서 bind, call, apply를 해주면 this를 명시할 수 있다.)
inner2() -> this: window(화살표 함수 이므로 부모인 sayN의 this)
inner1() -> this: window
sayN() -> this: window
inner4() -> this: window(화살표 함수이므로 부모인 sayName2의 this)
inner3() -> this: window
obj.sayName2() -> this: window(화살표 함수이므로 부모인 anonymous의 this)
bindedInner() -> this: obj(일반함수에서 bind, call, apply를 해주면 this를 명시할 수 있다.)
inner2() -> this: obj (화살표 함수의 this 부모의 this 그러므로 부모인 sayName의 this)
inner1() -> this: window
obj.sayName() -> this: obj (객체로 부터 호출 일반함수의 this는 자신을 호출한 객체)
anonymous -> this: window

profile
시작.

0개의 댓글