함수 호출 방식에 의해 결정되는 this
자바스크립트의 함수는 호출될 때, 매개변수로 전달되는 인자값 이외에, arguments 객체
와 this
를 암묵적으로 전달받는다.
이를 이해하려면 실행 컨텍스트를 이해해야 하는데, 다음과 같다:
- 자바스크립트가 실행되는 환경을 정의
- this, 변수, 객체, 함수 등 코드의 실행에 필요한 기반
- 식별자, 스코프, this 등은 ‘렉시컬 환경‘을 기반으로 관리됨
- ‘클로저’ : 자신이 생성될 때의 환경을 기억하고 그를 사용하는 함수. 현재 실행중인 코드에 대한 세부정보( 제어 흐름의 위치, 선언된 변수와 함수, this, arguments 등)을 담고있는 데이터 구조. 실행 컨텍스트 스택이라는 자료구조에 저장되고 관리된다 === 호출스택(call stack)
들어가면서…
알고리즘으로 파이썬을 공부할 때, self(this) 의 경우는 인스턴스 자신을 가리키는 참조변수로 사용했었다. 예를 들어 다음과 같다.
1
2
3
4
class Node:
def __init__(self, data, next = None):
self.data = data
self.next = next
자바스크립트의 경우, 함수 호출 방식에 따라 this 에 바인딩되는 객체가 달라진다.
함수 호출 방식과 this 바인딩
함수의 상위 스코프를 결정하는 방식인
렉시컬 스코프(Lexical scope)
는 함수를 선언할 때 결정된다. this 바인딩과는 다르다.
함수 호출 방식에 따라 달라진다고 하는데, 그러면 함수 호출하는 방식은 뭐가있을까 :
- 함수 호출
- 메소드 호출
- 생성자 함수 호출
- apply/call/bind 호출
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const foo = function () {
console.dir(this);
};
// 1. 함수 호출
foo(); // window === window.foo();
// 2. 메소드 호출
const obj = { foo: foo };
obj.foo(); // obj
// 3. 생성자 함수 호출
const instance = new foo(); // instance
// 4. apply/call/bind 호출
const bar = { name: "bar" };
foo.call(bar); // bar
foo.apply(bar); // bar
foo.bind(bar)(); // bar
1. 함수 호출
전역 객체(Global Object)는 모든 객체의 유일한 최상위 객체를 의미. 일반적으로 Browser-side 에서는 window
, Server-side(Node.js) 에서는 global
객체를 의미.
1
2
3
4
5
6
// in browser console
this === window; // true
// in Terminal
node;
this === global; // true
기본적으로 this
는 전역객체(Global object) 에 바인딩된다. 전역함수는 물론이고 심지어 내부함수의 경우도 this
는 외부함수가 아닌 전역객체에 바인딩 된다.
1
2
3
4
5
6
7
8
9
function foo() {
console.log(this); // window
function bar() {
console.log(this); // window
}
bar();
}
foo();
또한 메소드의 내부함수일 경우에도 this
는 전역객체에 바인딩된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var value = 1;
var obj = {
value: 100,
foo: function () {
console.log(this); // obj
console.log(this.value); // 100
function bar() {
console.log(this); // window
console.log(this.value); // 1
}
bar();
}
};
출처