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)