본 시리즈는 JS를 공부하며 알게된 JS만의 특성이나 프로그래밍 기본기로써 중요한 내용들을 묶어 정리하는 시리즈입니다.
정해져있는 순서는 없으며, 각 항목들이 큰 연관을 갖고있지는 않습니다.
추후에 체계적으로 정리하여 글을 수정할 계획은 있습니다.
이번에는 짤막글이 되겠다.
간단명료하게 JS의 특이한 this에 대해서 짚어보도록 하자.
다음의 코드를 보자.
let user = {
name: "John",
age: 30,
sayHi() {
// 'this'는 '현재 객체'를 나타냅니다.
alert(this.name);
}
};
user.sayHi(); // John
위의 코드에서 this
는 무엇을 가리킬까? 보통의 경우, 메소드 내부에서 this
를 호출하면, 메소드 자신을 갖고있는 객체에 대해 접근한다. 즉, 객체 내부의 메소드는 this
를 통해 객체 프로퍼티를 이용하게 된다. 위의 코드에서는 this가 sayHi()
메소드를 갖고있는 user
객체를 가리킨다.
그런데 JS의 this
는 조금 특이한 점이 있다. 이제부터 알아보자.
function sayHi() {
alert(this);
}
sayHi();
JS에서는 this
를 이렇게 모든 함수에 대해서 사용할 수 있다. 그렇다면, 위의 코드를 실행한 결과는 어떻게 되는가?
정답은 undefined가 출력된다.
객체 내부에서 호출되어 this가 가리킬 객체가 없다면, this는 undefined로 초기화된다.
그리고 또 하나의 독특한 점은, JS의 this
가 가리키는 대상은 런타임에서 결정된다는 것이다.
다음의 코드를 보자.
let user = { name: "John" };
let admin = { name: "Admin" };
function sayHi() {
alert( this.name );
}
// 별개의 객체에서 동일한 함수를 사용함
user.f = sayHi;
admin.f = sayHi;
user.f();
admin.f();
admin['f']();
위 코드의 실행 결과는 어떻게 될까?
user.f() 에서는 'John'을, admin.f()에서는 'Admin'을 출력할 것이다.
최초에 sayHi가 정의될 때는 this.name이 undefined 였을 것이다. 가리키고 있는 this가 없기 때문이다.
그런데 이 sayHi는 user와 admin의 메소드가 되었고, 이 메소드가 실행될 때 this가 가리킬 대상이 정해졌다. user 메소드 sayHi의 this는 user를, admin 메소드 sayHi의 this는 admin 객체를 가리키게 되는것이다.
이렇게 신기할 수가 없다.
신기한 것 하나 더 알아보자.
let user = {
firstName: "보라",
sayHi() {
let arrow = () => alert(this.firstName);
arrow();
}
};
user.sayHi();
위 코드의 실행 결과는 어떻게 될까?
답은 '보라'이다.
화살표 함수에서 this를 사용하면, 이 this는 아무런 값을 가지고 있지 않게된다. 즉, 별도의 컨텍스트를 가리키는 this가 아닌 평범한 외부 함수(객체)를 가리키는 this를 사용하고 싶을 경우 화살표 함수를 이용하면 된다.
위의 코드에서는 화살표함수의 this가 자신이 선언된 sayHi()의 this를 사용하게 되고, sayHi()의 this는 자신이 선언된 user 객체를 가리키고 있다. 따라서 user 객체의 firstName에 접근할 수 있게 된다.
이제부터 예제를 통해 this를 조금 더 알아보도록 하자.
let ladder = {
step: 0,
up() {
this.step++;
},
down() {
this.step--;
},
showStep: function() { // 사다리에서 몇 번째 단에 올라와 있는지 보여줌
alert( this.step );
}
};
ladder.up().up().down().showStep();
위의 코드가 정상 동작하도록 ladder 객체를 수정해보자.
답은 다음과 같다.
let ladder = {
step: 0,
up() {
this.step++;
return this;
},
down() {
this.step--;
return this;
},
showStep: function() { // 사다리에서 몇 번째 단에 올라와 있는지 보여줌
alert( this.step );
}
};
각 메소드에서 this를 return하도록 하면 그 메소드의 this가 참조하는 외부 객체인 ladder가 반환된다. 즉, 문제의 코드에서 각 메소드가 실행될때마다 반환된 ladder 함수에 대해 재차 메소르를 호출하는 체이닝을 구현할 수 있게 된다.
this에 대해서 더 정확히 알기 위해선 context에 대한 이해가 필요한데, JS의 context는 별도의 게시글에서 다루도록 하겠다.