1. Execution Context
Javascript engine은 code가 실행되면 제일 먼저 Global memory를 생성한다.
이 Global memory에는 변수와 함수들의 이름과 값(주소)이 memory table 형태로 저장되는데, 이것을 execution context라고 부른다.
Global execution context는 코드의 모든 것을 포함하는 전역 컨텍스트이며, 페이지가 종료될 때까지 유지된다.
이후 함수가 하나 호출될 때마다 local execution context가 생긴다.
(단순 block 단위에서는 생기지 않고, 함수 단위에서만 생긴다.)
execution context가 생성되면, context 안에 arguments, variable(변수 및 함수), scope, chain, this가 생성된다.
1
2
3
4
5
6
7
8
9
10
11
|
function j(){
let a = 'alpha';
console.log("I'm " + a)
}
function k(){
let b = 'beta';
console.log("I'm " + b)
j() }
k()
|
cs |
위와 같이 코드를 작성하면, j scope execution context, k scope execution context, global scope execution context가 생성되게 된다.
아래처럼, debugging을 해보면, k() 함수가 실행되면서 내부의 j 함수도 실행되고,
j 함수가 실행되면서 execution context가 생성되고, call stack에 j 함수가 쌓인 것을 볼 수 있다.
Call stack에서의 anonymous는 global execution context인 window 이다.
2. this
이제 execution context가 생성될 때 자동으로 만들어지는 this를 알아보자.
this는 모든 함수의 scope 내에서 자동으로 설정되는 특수한 식별자이다.
보통의 언어에서는 Class를 만들 때, (앞으로 만들어질) Instance를 가리키기 위해 'this'를 사용하지만,
(참조 - Javascript / 기초 / 객체지향 (Object-oriented))
javascript에서는 특별히 5가지 경우로 this의 쓰임새가 나누어진다.
1. Global에서 사용할 경우, window를 가리킨다.
2. function 호출 시, window를 가리킨다.
3. Method로 호출 시, 부모 object를 가리킨다.
4. Construction mode 시, 새로 생성된 객체를 가리킨다.
5. .call 이나 . apply로 호출 시, call, apply의 첫번째 인자로 명시된 객체를 가리킨다.
1, 2 Global 사용 및 function 호출 Case (Function Invocation)
그냥 this를 호출하거나, 전역으로 사용(var 선언), 또는 함수 선언식에서 사용 시
this는 전역 execution context를 가리키는 window와 같음을 알 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//전역에서 this 호출
this
Window {parent: Window, opener: null, top: Window, length: 4, frames: Window, …} // 결과
//this.greeting = window.greeting
var greeting = 'hello';
this.greeting
"hello" // 결과
//함수를 만들고, this 사용 시에도 this.greeting = window.greeting
function a(){
console.log(this.greeting)
}
a()
hello // 결과
|
cs |
3. Method 호출 (Method Invocation)
method 형태의 호출 시에는 this가 직계 부모요소를 가리킨다.
사실상 global execution context를 가리키는 1, 2의 경우도 직계부모가 window이기 때문에 window를 가리키는 것으로,
3. Method 호출의 원리와 같다고 할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
//함수를 요소로 갖는 객체(ob) 생성
let ob = {
c : {
d : function() { console.log(this); }
},
e : function() { console.log(this); }
}
// 1. Method 호출 방법을 통해 c 내부의 d 호출 시, 직계부모인 c = {d : f}를 this로 가리킴
ob.c.d();
{d: ƒ} // 결과
// ※ 함수가 아닌 c를 호출하거나, c의 언급없이 d를 호출할 수 없음
ob.c()
VM1063:1 Uncaught TypeError: ob.c is not a function
at <anonymous>:1:4
(anonymous)
ob.d()
VM1087:1 Uncaught TypeError: ob.d is not a function
at <anonymous>:1:4
(anonymous)
// 2. e를 호출 시, this는 직계부모인 ob를 가리키므로 ob = {c : { ...}, e : f} 가 나옴
ob.e()
{c: {…}, e: ƒ}
|
cs |
문제)
1
2
3
4
5
6
7
8
9
10
11
|
var obj = {
sum: function(a, b) {
return this
}
}
var obj2 = {
pro: obj.sum
};
console.log(obj2.pro())
// 결과 : {pro: f} // === obj2
|
cs |
>> obj2.pro를 method 호출 방식으로 호출하면, 호출된 그 순간의 직계 부모 요소를 this로 보므로,
obj2.pro() === obj2 가 된다.
4. Construction mode로 생성된 객체
가장 대표적인 예가 바로 Class의 instance를 가리키는 this 이다. 다른 언어에서와도 공통된 부분으로, 예제 및 설명은 다음 링크에서 확인할 수 있다.
Javascript / 기초 / 객체지향 (Object-oriented)
5. .call .apply의 첫번째 인자
함수를 호출할 때, 단순 '함수명()' 방식이 아니라, .call, .apply로도 호출할 수 있다.
이 때 첫 번째 파라미터로 객체를 입력할 수 있는데, 그렇게 되면 .call, .apply 에서의 this는 이 첫번째 파라미터인 객체를 가리키게 된다.
1
2
3
4
5
6
7
8
|
function hello(){
console.log(this);
}
var obj = { hello: 'world'}
hello.call(obj) // hello 함수는 this를 출력하고, 그것은 call method의 인자 obj가 된다.
{hello: "world"}
|
cs |
생각해보면, call과 apply도 construction mode로 생성된 객체(Class의 Instance)를 가리키는 this와 같은 원리라고 할 수 있다.
1
2
3
4
5
6
7
|
class Car {
constructor(name){
this.name = name;
}
let car = new Car
car.name = "Hyundai"
|
cs |
Class를 만들 때, 향후에 만들 Instance(car)의 이름이 어떻게 될지 모르므로, 만들어질 instance의 이름을 'this'로 정의하였다.
위 call, apply 사례에서도 함수를 만들 때, 어떤 객체를 불러올지 모르는 상황이라면 this를 사용하는 것이다.
다시 말해 hello 함수는 console.log를 통해서 뭔가를 출력은 하는데, 출력할 대상(객체)을 this로 만들어놓고, call이나 apply를 통해서 this를 지정하게 되는 것이다.
this, call 또는 bind에 대한 내용은 다음 글에 이어진다.
'Programming-[Frontend] > Javascript' 카테고리의 다른 글
Javascript / 함수 / call, apply, bind (0) | 2020.08.27 |
---|---|
Javascript / Array / sort (0) | 2020.08.25 |
Javascript / API, Server 기초 개념 (0) | 2020.08.24 |
Javascript / 비동기 호출의 개념, 타이머 API 기본 (0) | 2020.08.24 |
Javascript / DOM / template (0) | 2020.08.22 |