this라는 매개변수는 객체지향 프로그래밍 관점에서 중요한 역할을 차지한다고 생각한다. JavaScript에서도 함수, 클래스를 호출할 때 this 매개변수를 사용할 수 있다. 그런데 호출하는 패턴에 따라 각기 this가 다르게 동작한다. 오늘은 각 경우에 따라 this가 어떻게 되는지 살펴본다.
this가 호출되는 패턴은 다음과 같이 네 가지가 있는 것 같다
- 메소드 호출 패턴
- 함수 호출 패턴
- 클래스 호출 패턴
- apply 호출 패턴
각각의 경우에 대해 this가 어떻게 다른지 자세히 살펴보자.
1. 메소드 호출 패턴
함수를 객체의 속성에 저장하는 경우 이 함수를 메소드라고 부른다. 이 경우는 메소드를 호출할 때, this는 메소드를 포함하고 있는 객체에 바인딩된다. 즉, 흔히 예상하는 것 처럼 this는 객체 자체가 된다.
var myObject1 = {
value: 0,
increment: function (inc) {
this.value += typeof inc === 'number' ? inc: 1;
}
};
myObject1.increment();
console.log(myObject1.value); // 1
myObject1.increment(2);
console.log(myObject1.value); // 3
이때 method(increment부분)를 다음과 같이 줄여서 표현할 수도 있고, 이 방식을 [1] Airbnb JavaScript Guide 에서도 권하고 있다.
var myObject1 = {
value: 0,
increment (inc) {
this.value += typeof inc === 'number' ? inc: 1;
}
};
하지만, 메소드 호출 패턴을 사용할 때, 화살표 함수(arrow function)의 this는 [2] this는 객체에 바인딩 되지 않는다. 사실 어느 곳에도 바인딩 되지 않는다. 이 점으로 보아, 메소드 내에서 this를 사용해야 하는 경우 화살표 함수로 메소드를 선언하지 않도록 주의해야 겠다.
var myObject2 = {
value: 0,
increment: (inc) => {
this.value += typeof inc === 'number' ? inc: 1;
}
};
myObject2.increment( );
console.log(myObject2.value); // 0
myObject2.increment(2);
console.log(myObject2.value); // 0
일반적으로 매소드 호출 패턴에서 this는 메소드를 호출할 때 객체의 속성들에 접근해 읽거나 쓰기를 할 때 사용된다. 하지만 화살표 함수 내에서 this는 메소드 호출시, 현재 context에 바인딩이 일어나서 this가 객체를 바인딩하지 않는다. 이것을 늦은 바인딩(lexical binding)이라 부른다. http://www.javascriptkit.com/javatutors/javascriptarrowfunctions2.shtml
2. 함수 호출 패턴
함수에서 this는 전역객체에 바인딩된다. 따라서 함수 호출 패턴에서는 this를 사용하지 말자! 또는 [3] bind( )를 사용하자!
var add = function add(a, b) {
var sum = 0;
this.sum = a + b;
return this.sum;
}
console.log(add(3,4)); // 7
console.log(sum); // 7
아래 사진에서 볼 수 있듯이 VS Code debug로 봤을 때 this는 global 객체에 바인딩 됐음을 알 수 확인할 수 있다.
3. 클래스 호출 패턴
이 패턴은 흔히 객체지행 프로그래밍에서 사용되는 패턴이라 이해하는데 크게 어려움이 없을 것이다. this는 p1이라는 인스턴스가 생성될 때 그곳에 바인딩된다.
class Person {
constructor(name='noName') {
this.name = name;
}
}
var p1 = new Person();
console.log(p1.name); // noName
4. apply 호출 패턴
아래 코드와 같이 apply는 객체 내부의 this를 바꾼다. 참고로, apply 메소드는 함수의 매개변수를 넘길 때 this도 함께 넘길 때 사용된다. (사실 apply가 어디에 주로 쓰이는 지는 모르겠다. 이 부분은 보완 필요!)
var myObject1 = {
value: 0,
increment(inc) {
this.value += typeof inc === 'number' ? inc: 1;
}
};
var changeThis = function () {
this.value = -1;
}
myObject1.increment();
console.log(myObject1.value) // 1
changeThis.apply(myObject1, null);
console.log(myObject1.value); // -1
참고
[1] https://github.com/airbnb/javascript#es6-object-shorthand%5D(https://github.com/airbnb/javascript#es6-object-shorthand
[2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
[3] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
'Programming language > JavaScript' 카테고리의 다른 글
JavaScript, Prototype (0) | 2020.11.14 |
---|---|
JavaScript Promise의 all( )과 race( ) (0) | 2019.03.23 |
자바스크립트, Promise로 요청실패시 retry 처리하기 (0) | 2019.03.22 |
JavaScript callback hell과 async-await (0) | 2017.11.01 |