실행 컨텍스트

김종현·2023년 3월 15일
0

Js

목록 보기
14/16

동기/비동기

공부를 하다가 배달을 시켰다
비동기)배달이 오는 동안 공부를 하다가 밥이 오면 먹는다
동기)배달이 오는 동안 공부에서 손을 놓고 있다가 밥이 오면 먹는다

실행 컨텍스트(Execution context)

-실행 컨텍스트 or 실행 맥락은 Js code가 실행되는 환경.
-코드에서 참조하는 변수, 객체(함수 포함), this 등에 대한 레퍼런스가 있다.(레퍼런스 변수가 있다)
-실행 컨텍스트는 전역에서 시작해 함수가 호출될 때 스택에 쌓이게 된다.
-아무 코드도 없을 때는 전역 컨텍스트가 만들어지고 함수가 실행될 때는 함수 컨텍스트가 만들어진다.

자바스크립트 코드의 실행

-자바스크립트 엔진은 코드가 없어도 실행 당시의 환경(실행컨텍스트-Execution Context)을 초기화 한다.

-코드가 없어도 다음의 세 가지 변수를 초기화.

  • This : window(최상위 스코프) - 코드가 실행되는 시점의 환경이 가르키는 객체
  • Variable objects(변수들) : {}
  • Scope chain(스코프 체인) : [ ](최상위 스코프에서 연결된 스코프가 없으므로 빈 상태, 바로 이전의 실행 컨텍스트를 가리켜 만약 다른 변수를 찾아야 할 경우 스코프 체인을 따라 변수를 검색하게 된다.

-스코프(scope)는 코드가 현재 실행되는 환경, 맥락(context)을 의미한다.
-this 포인터, 스코프에 저장된 변수들, 스코프 체인 등이 환경에 포함된다.
-this 포인터(레퍼런스 변수)의 경우, 글로벌 스코프에서는 window를 가리킨다.

특정 함수가 존재하고 그 함수가 실행되는 경우

선요약
-실행 컨텍스트는 call stack이다.
ㄴ쌓이는 순서는 '함수가 실행 되는 순서'
ㄴ제거되는 순서는 '마지막에 실행 된 것 부터'
-함수가 실행되면, 함수 스코프에 따라 환경이 만들어진다.
-this, 함수 스코프의 변수들, 스코프 체인이 형성된다.
-스코프 체인을 따라 글로벌 환경에 도달한다.

-> 최상위 컨텍스트 생성  this, variable objects, scope chain 생성  <-
function myFunc(){
	let a = 10
	let b = 20
	function add(frst, second){
		return first + second
	}
return add(a,b)
}

myFunc();

★call stack : 실행 컨텍스트는 스택 구조()로 이루어진다.
a-b-c 순으로 위에 쌓인다.

  • ★쌓이는 순서는 '함수가 실행 되는 순서'
  • ★제거되는 순서는 '마지막에 실행 된 것 부터'

ⓒadd function의 실행으로 만들어진 컨텍스트
this : undefined
variable object : { first: 10, second : 20 }
scope chain : [myFunc, global] - add 밖의 scope : myFunc, myFunc 밖의 scope : global

ⓑmy Func의 실행으로 만들어진 컨텍스트
this : undefinced(strict mode)
variable object : { a:10, b:20, add:function{...} }
scope chain : [global]

이후 myFunc의 실행이 완료되면 해당 컨텍스트는 제거된다

ⓐ기존에 생성된 글로벌 컨텍스트는 여전히 존재
this : window
variable object : {}
scope chain : []

모든 코드의 실행이 완료되면 글로벌 컨텍스트 또한 제거된다.
즉, 모든 함수의 호출이 끝났을 때 전역 실행 컨텍스트로 돌아가게 된다.

객체가 존재하고 해당 객체의 메서드를 호출하는 경우

선요약
-객체의 메서드의 경우, 메서드 환경의 this는 해당 객체를 가리킨다
-그러나 this가 가리키는 것은 this가 포함된 코드가 실행 되는 환경과 맥락에 따라 변할 수 있다


let 0 = {
  name: 'Daniel',
  method : function(number){
    return this.name.repeat(number);
  }
}
//this = o
function myFunc(){
  let n = 10
  return o.method(n)
}

myFunc()

ⓒ let o 의 실행 컨텍스트
this : o
variable object : { number:10 }
scope chain : [global]

ⓑ myFunc의 실행 컨텍스트
this : undefined
variable object : { n:10 }
scope chain : [global]

ⓐ 글로벌 컨텍스트
this : window
variable object : { o:{...}, myFunc:function(){..} }
scope chain : []

-함수를 다른 함수의 인자로 넘기면 다른 함수 내부에서 그 함수를 호출할 수 있다
=>함수를 인자로 받아 활용, 인자로 받은 함수는 또한 다른 함수를 인자로 받을 수 있음.
-함수 안에 함수를 만들어 외부에서 쓸 수 있다
=>함수 안에 함수 선언 후 외부에서 쓰고 싶다면 그 함수를 리턴하여 사용.
-함수의 실행이 끝나도 내부 변수를 유지할 수 있다
=>함수 안에서 클로저가 만들어지면 내부 변수가 메모리에 남아 클로저에 활용된다.

실행 컨텍스트의 스택

선요약
-자바스크립트가 실행될 때 전역 실행 컨텍스트(Global Execution Context)가 만들어진다.
-함수가 실행될 때 함수 실행 컨텍스트(Function Execution Context)가 만들어진다.

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();

-전역에 존재하는 코드/ 함수에 존재하는 코드를 잘 구별해야 하낟.
①전역에 존재하는 코드 : 함수나 클래스 내부의 코드를 무시하고 컨텍스트를 가진다.
②함수에 존재하는 코드 : 함수 내부에서만 컨텍스트를 가진다.
이들은 호출되는 순서에 따라 스택에 쌓이고 나중에 쌓여진 함수부터 실행된다.

스택 순서
ⓐ 글로벌 실행 컨텍스트의 변수: a, console.log(), f:f1

  • console.과 같은 전역 객체를 참조했을 때도 마찬가지로 스코프 체인을 따라서 전역 실행 컨텍스트까지 참조를 하게 된다.
  • 실상은 window 객체 밑에 있는 변수지만 편의상 전역에서 참조 가능하므로 여기에 위치

스코프 체인 순서
d->c->b->a

ⓑ 함수 f1 실행 컨텍스트의 변수 : b, f:print, f:f2
ⓒ 함수 f2 실행 컨텍스트의 변수 : c
ⓓ 함수 print 실행 컨텍스트의 변수 : v

렉시컬 환경

-식별자와 식별자에 연결된 값을 저장하는 자료구조.

const myName = 'kim'

function House() {
	const title = "home"
    return title;
}

-전역으로 생성되는 렉시컬 환경에서는 myName, House 이렇게 2개의 변수와 변수에 연결된 값이 저장된다.
-myName엔 'kim'이 들어있지만 스코프 체인으로 House와 연결되어있다.
-House함수의 렉시컬 환경에서는 title이라는 변수와 해당 변수에 연결된 값이 저장된다. 또한 전역 렉시컬 환경에 스코프 체인으로 연결되어 있다. 왜냐하면 전역에서는 House라는 정보를 갖고 있기 때문이다.

const o1 = {
  name : 'kim'
  changeName: function (name) { this.name = name},
};

const o2 = {
  name : 'lee'
}

function call(f, arg) {
  f(arg);
}

o.changeName.bind(o2)('lee');
console.log('1번-', o2.name);
call(o.changeName, 'park');
console.log('2번-', o.name);
o.changeName('lee');
console.log('3번-', o.name);

-1번이 lee인 이유는 bind 메서드로 기존 o의 실행컨텍스트를 o2의 실행컨텍스트로 변환했기 때문이다.
-2번이 ki인 이유는 o의 changeName 메서드는 call 함수의 인자로 넘겨질 때 실행컨텍스트가 dynamic binding 되기 때문이다. 따라서 o.changeName은 global을 실행컨텍스트로 갖게 되고 o.name은 바뀌지 않는다.
-3번이 lee인 이유는 o.changeName 메서드의 실행 컨텍스트가 o로 유지되기 때문이다.

profile
나는 나의 섬이다.

0개의 댓글