[JS] this

this

자바스크립트에서의 this함수의 현재 실행 문맥이다.

함수 실행에서의 this

함수 실행에서의 this는 전역 객체다. 전역 객체는 실행 환경에 따라 결정되는데, 웹 브라우저에서는 window가 전역 객체다. 아래의 예시를 보자.

1
2
3
4
5
6
7
8
9
10
function sum(a, b) {
document.write(this === window); // true
this.myNumber = 20;
return a + b;
}

var obj = sum(15, 16);
document.write(obj); // 31
document.write(obj.myNumber); // undefined
document.write(window.myNumber); // 20

7행에서 sum함수를 호출한 결과를 obj라는 변수에 넣었다. sum함수의 매개변수로 1516을 전달했고, 1행의 sum함수가 실행된다.

이 때, 7행에서 sum함수를 호출할 때의 this는 전역 객체인 window이므로 2행에서 this === window의 결과는 true이다.

그 후, 3행에서 window객체의 myNumber20을 저장한 뒤, 4행에서 1516을 더하여 반환한다. 그 반환 값은 7행의 obj에 저장되기 때문에, 8행의 결과는 31이다.

그리고 9행의 obj.myNumber은 정의한 적이 없기 때문에 undefined이며, 10행의 window.myNumber은 아까 3행에서 20으로 저장했기 때문에 20을 출력한다.

그렇다면 이번엔 다음 예제를 보자.

1
2
3
4
5
6
7
8
9
function sum(a, b) {
document.write(this === window); // false
this.myNumber = 20;
return a + b;
}
var obj = new sum(15, 16);
document.write(obj); // [object Object]
document.write(obj.myNumber); // 20
document.write(window.myNumber); // undefined

이번엔 sum형 객체로 obj를 생성했다. 객체를 생성했을 때의 this는 그 객체 자신이 되기 때문에 2행에서의 thisobj이다. 따라서 this === window의 값은 false이다.

3행에서 this.myNumberobj.myNumber을 의미하기 때문에 obj.myNumber20을 저장한다.

그리고 obj는 객체이기 때문에 7행에서 obj의 출력 결과는 [object Object]이다.

8행의 실행 결과는 아까 저장한대로 20이며, window.myNumber은 정의한 적이 없기 때문에 undefined이다.


엄격 모드 함수 실행에서의 this

엄격 모드에서 함수 실행에서의 thisundefined이다. 그리고, 엄격 모드는 현재 스코프 뿐만 아니라 내부 스코프에서도 적용된다.

1
2
3
4
5
6
7
8
9
function sum(a, b) {
'use strict'; // 엄격 모드
document.write(this === window); // false
document.write(this === undefined); // true
return a + b;
}

var num = sum(2, 5);
document.write(num); // 7


내부 함수에서의 this

내부 함수의 문맥은 외부 함수의 문맥에 의존되는 게 아니라 오로지 실행 환경에 좌우된다. 아래의 예시를 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var numbers = {
numA: 5,
numB: 10,
sum: function() {
document.write(this === numbers); // true
function calc() {
document.write(this === numbers); // false
document.write(this === window); // true
return this.numA + this.numB;
}
return calc();
}
};

var result = numbers.sum();
document.write(result); // NaN

numbers.sum()은 객체 내에 있는 메소드를 실행하는 것이기 때문에 sum메소드 내의 문맥은 numbers객체다. 즉, 5행에서 외부 함수의 thisnumbers인 것이다. 하지만 calc함수는 sum함수 내부에 정의되었다. 이 때 thiswindow이다. 또한 이 때 9행에서 thiswindow이기 때문에 16행의 출력결과는 NaN이 되는 것이다.

이러한 문제를 해결하기 위해서 calc함수도 sum메소드와 동일한 문맥 상에 있어야 한다. 그래야 numAnumB속성에 접근할 수 있기 때문이다. 이를 해결하려면 call이나 apply또는 bind를 사용하면 된다. 여기서는 call메소드를 사용하여 해결해보겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var numbers = {
numA: 5,
numB: 10,
sum: function() {
document.write(this === numbers); // true
function calc() {
document.write(this === numbers); // true
document.write(this === window); // false
return this.numA + this.numB;
}
return calc.call(this);
}
};

var result = numbers.sum();
document.write(result); // 15

11행의 this는 외부 함수인 sum메소드에 속하기 때문에 numbers이다. 따라서 calc.call(this)numbers객체에 calc라는 메소드를 등록해주는 셈이기 때문에, calc메소드의 thisnumbers가 된다.

Share