0%

[Javascript] this 정리

자바스크립트 this 바인딩

자바스크립트의 this는 현재 실행 문맥이다. 여기서 현재 실행 문맥이라는 건 무엇을 뜻할까? 바로 호출자를 뜻한다.
호출자는 크게 세 가지로 나뉘어진다. 첫 번째는 객체의 메소드, 두 번째는 함수, 그리고 마지막으로 생성자 함수이다. 만약 this가 나온다면 이 세 가지 경우 중 하나이니 누가 호출했는지 보고 this가 어떤 의미를 가지는지를 따져보면 된다. 이를 함수 호출 패턴이라고 하며, 자바스크립트의 this 는 함수 호출 패턴에 따라 this 가 어떤 객체의 this 가 될 지 정해진다. 이를 this 바인딩이라고 한다.
바인딩(biding)의 사전적 의미는 묶이다인데, 누가 호출했는지에 따라 this가 호출자에게 묶인다는 의미로 이해하면 그나마 이해하기 쉬워진다.

1. this 바인딩의 호출 패턴

  • 객체의 메소드를 호출할 때의 this 바인딩
  • 함수를 호출할 때의 this 바인딩
  • 생성자 함수를 호출할 때의 this 바인딩

1.1 객체의 메소드 호출할 때 this 바인딩

자신을 호출한 객체에 바인딩이 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
var obj = {
sayName: function() {
console.log(this.name);
}
};

var kim = obj;
kim.name = "kim";
kim.sayName(); // "kim"

var lee = obj;
lee.name = "lee";
lee.sayName(); // "lee"

1.2 함수를 호출할 때 this 바인딩

전역 객체(window)에 바인딩이 된다.

1
2
3
4
5
6
7
8
9
var val = "Hello";

var func = function() {
console.log(this.val);
};
func(); // "Hello"
console.log(this.val); // "Hello"
console.log(window.val); // "Hello"
console.log(this === window); // true

하지만 함수 호출에서의 this 바인딩은 내부 함수를 호출할 때도 그대로 적용이 된다. 아래 예제를 보면, 결과가 2,3,4 로 나와야 할 것 같지만 그렇게 나오지 않는다. 왜냐면 자바스크립트가 내부 함수 호출 패턴을 정해놓지 않았기 때문에, 내부 함수도 함수 취급을 받아 이러한 결과가 나온 것이다.
따라서 함수 호출 패턴 패턴 규칙에 따라 내부 함수의 this 는 전역 객체(window)에 바인딩된다.

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
// 전역 변수 value 정의
var value = 100;

// myObject 객체 생성
var myObject = {
value: 1,
func1: function() {
this.value += 1;
console.log("func1() called. this.value : " + this.value);

// func2() 내부 함수
func2 = function() {
this.value += 1;
console.log("func2() called. this.value : " + this.value);

// func3() 내부 함수
func3 = function() {
this.value += 1;
console.log("func3() called. this.value : " + this.value);
};

func3(); // func3() 내부 함수 호출
};
func2(); // func2() 내부 함수 호출
}
};
myObject.func1(); // func1() 메소드 호출

위와 같은 상황을 피하려면, 부모 함수의 this 를 내부 함수가 접근 가능한 다른 변수에다 저장해야 한다. 보통 this 값을 저장하는 변수의 이름을 that 이라고 짓는다.

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
// 내부 함수 this 바인딩
var value = 100;

var myObject = {
value: 1,
func1: function() {
var that = this; // 부모 함수의 this를 that으로 저장

this.value += 1;
console.log("func1() called. this.value : " + this.value);

func2 = function() {
that.value += 1;
console.log("func2() called. this.value : " + that.value);

func3 = function() {
that.value += 1;
console.log("func3() called. this.value : " + that.value);
};
func3();
};
func2();
}
};

myObject.func1(); // func1 메소드 호출

1.3 생성자 함수를 호출할 때 this 바인딩

new 로 생성자 함수를 생성한 객체에 바인딩이 된다.

1
2
3
4
5
6
7
8
9
var Person = function(name) {
this.name = name;
};

var kim = new Person("kim");
console.log(kim.name); //kim

var lee = new Person("lee");
console.log(lee.name); //lee