공부를 하다가 배달을 시켰다
비동기)배달이 오는 동안 공부를 하다가 밥이 오면 먹는다
동기)배달이 오는 동안 공부에서 손을 놓고 있다가 밥이 오면 먹는다
-실행 컨텍스트 or 실행 맥락은 Js code가 실행되는 환경.
-코드에서 참조하는 변수, 객체(함수 포함), this 등에 대한 레퍼런스가 있다.(레퍼런스 변수가 있다)
-실행 컨텍스트는 전역에서 시작해 함수가 호출될 때 스택에 쌓이게 된다.
-아무 코드도 없을 때는 전역 컨텍스트가 만들어지고 함수가 실행될 때는 함수 컨텍스트가 만들어진다.
-자바스크립트 엔진은 코드가 없어도 실행 당시의 환경(실행컨텍스트-Execution Context)을 초기화 한다.
-코드가 없어도 다음의 세 가지 변수를 초기화.
-스코프(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
스코프 체인 순서
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로 유지되기 때문이다.