this란?
일반적으로 대부분의 언어에서 this 키워드는 자기 자신의 인스턴스를 가리키는 용어이다.(python에서는 self 키워드)
하지만, javascript의 this 키워드는 다른 언어와는 다른 방식으로 작동한다.
* chrome 브라우저 환경에서 테스트한 결과입니다. node의 경우 window 전역 객체 대신 global 전역 객체를 사용하는데, global이 제대로 반환되지 않아서 브라우저 환경에서 진행하였습니다.
Java에서의 this
class Test {
public int number;
public void setNumber(int number){
this.number = number
}
}
class Main {
public static void main(String[] args){
Test t1 = new Test();
Test t2 = new Test();
t1.setNumber(1);
t2.setNumber(2);
System.out.println(t1.number); // 1
System.out.println(t2.number); // 2
}
}
당연하게도 Java에서의 this는 Test 인스턴스를 가리킨다는 것을 알 수 있다. 그렇다면 js에서는 어떻게 작동할까?
javascript에서의 this
this 바인딩 규칙
우선 설명 이전에, 바인딩 규칙부터 알아보자.
- 일반 함수(function 키워드 사용)에서 사용된
this는 해당 함수를 호출하는 객체를 가리킨다. - 화살표 함수에서 사용된
this는 block을 타고 올라갔을 때, 맨 처음 만나는 일반 함수의this를 가리킨다. new키워드를 사용할 경우 생성자 함수가 객체 그 자체가 된다. 생성자 함수는 일반 함수여야한다. 생성자 함수 호출 시this는 무조건 자기 자신이다.
첫 번째 규칙 - 일반 함수의 this
일반 함수(function 키워드 사용)에서 사용된
this는 해당 함수를 호출하는 객체를 가리킨다.
const test = {
setNumber: function(number) {
this.number = number
return this
}
}
const result = test.setNumber(1)
console.log(test.number) // 1
console.log(result === test) // true
해당 방식은 다른 언어와 유사하게 작동하는 것을 알 수 있다.
규칙에 맞게 따져보자.
setNumber함수가 일반 함수로 선언되어 있음.setNumber함수를test객체가 호출함.- ex.
test.setNumber(1)
- ex.
- ->
setNumber에서this=test
그렇다면 setNumber 함수를 다른 객체에서 사용하면 어떻게 될까?
const test = {
setNumber: function(number) {
this.number = number
return this
}
}
const other = {}
other.setNumber = test.setNumber
const result = other.setNumber(1)
console.log(test.number) // undefined
console.log(other.number) // 1
console.log(result === test) // false
console.log(result === other) // true
test의setNumber를other의setNumber로 옮김.other.setNubmer(1)을 실행.- ->
this=other임을 알 수 있음.
즉, 규칙에 따라, this는 일반함수를 호출하는 객체임을 알 수 있다.
두 번째 규칙 - 화살표 함수의 this
화살표 함수에서 사용된
this는 block 계층을 타고 올라갔을 때, 맨 처음 만나는 일반 함수의this를 가리킨다.
const test = {
setNumber: (number) => {
this.number = number
return this
}
}
const result = test.setNumber(1)
console.log(test.number) // undefined
console.log(result === test) // false
console.log(result === window) // true
해당 코드를 보면, setNumber 내부의 this 가 window 객체임을 알 수 있다. 왜 이런 현상이 발생한 것 일까?
규칙에 맞게 한번 따져보자,
setNumber는 화살표 함수임.setNumber의 상위 블록은 전역 객체인window임.- 맨 처음 만나는 일반 함수가 없었으므로,
window=this임을 알 수 있음.
이번엔 일반함수가 있는 경우를 알아보자
const test = {
setNumber: function (number) {
const run = (number) => {
this.number = number
return this
}
return run(number)
}
}
const result = test.setNumber(1)
console.log(test.number) // 1
console.log(result === test) // true
console.log(result === window) // false
이번 코드의 결과는 위의 결과와 완전히 정반대라는 것을 알 수 있다.
다시한번 규칙에 맞게 따져보자.
setNumber는 일반 함수임.setNumber내부에run이라는 화살표 함수가 존재함.setNumber는run을 실행한 후 결과를 반환함.run의 상위 계층 블록은setNumber이고,setNumber의 상위 계층 블록은window임.run에게는setNumber가 상위 계층 블록 중 처음 만나는 일반 함수이므로setNumber의this가 바로run의this임.setNumber를 호출한 객체는test객체임- 그러므로
this=test임을 알 수 있음.
세 번째 규칙 - new 키워드
new키워드를 사용할 경우 생성자 함수가 객체 그 자체가 된다. 생성자 함수는 일반 함수여야한다. 생성자 함수 호출 시this는 무조건 자기 자신이다.
class Test {
setNumber(number) {
this.number = number
return this
}
}
const test = new Test()
const result = test.setNumber(1)
console.log(test.number) // 1
console.log(result === test) // true
해당 코드는 setNumber가 일반함수이므로 당연히 this 가 test 임을 알 수 있다.
그런데 만약 아래와 같은 코드가 있다면 어떨까?
class Test {
setNumber = (number) => {
this.number = number
return this
}
}
const test = new Test()
const result = test.setNumber(1)
console.log(test.number) // 1
console.log(result === test) // true
해당 코드는 setNumber가 화살표 함수이므로, 앞서 말했던 것 처럼 this가 window가 될 것 같지 않은가?
그렇지 않다. 위 코드는 아래와 같은 코드이다.
const Test = function () {
this.setNumber = (number) => {
this.number = number
return this
}
}
const test = new Test()
const result = test.setNumber(1)
console.log(test.number) // 1
console.log(result === test) // true
js에서는 함수에 new를 붙여버리면, 그 함수가 생성자 함수가 되어버린다. 그리고 new는 일반 함수에만 붙일 수 있다.
그렇다면 setNumber의 맨 처음 만나는 상위 블록의 일반 함수가 생성자이고, 생성자의 호출시 this는 자기자신이므로 setNumber의 this는 test가 된다.
정리
해당 내용은 mdn web docs - this을 참고해서 작성한 글이다. 더 자세한 정보를 얻고 싶다면 문서에서 확인해보자.
this바인딩 정리- 일반 함수(function 키워드 사용)에서 사용된
this는 해당 함수를 호출하는 객체를 가리킨다. - 화살표 함수에서 사용된
this는 block을 타고 올라갔을 때, 맨 처음 만나는 일반 함수의this를 가리킨다. new키워드를 사용할 경우 생성자 함수가 객체 그 자체가 된다. 생성자 함수는 일반 함수여야한다. 생성자 함수 호출 시this는 무조건 자기 자신이다.
- 일반 함수(function 키워드 사용)에서 사용된
- 최상위
this는window이다.(node.js에서는 global)