[JavaScript] this

javascript

this

JavaScript에서의 this는 함수의 현재 실행 문맥이다.

함수 실행에서의 this

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

1
2
3
4
5
6
7
8
9
10
function sum(a, b) {
  console.log(this === window); // true
  this.myNumber = 20;
  return a + b;
}
 
var obj = sum(1516); 
console.log(obj); //31
console.log(obj.myNumber); // undefined
console.log(window.myNumber); // 20
cs

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) {
  console.log(this === window); // false
  this.myNumber = 20;
  return a + b;
}
var obj = new sum(1516); 
console.log(obj); // [object Object]
console.log(obj.myNumber); // 20
console.log(window.myNumber); // undefined
cs

이번엔 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'//엄격 모드
  console.log(this === window); // false
  console.log(this === undefined); // true
  return a + b;
}
 
var num = sum(25);
console.log(num); // 7
cs

내부 함수에서의 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() {
    console.log(this === numbers); // true
    function calc() {
      console.log(this === numbers); // false
      console.log(this === window); // true
      return this.numA + this.numB;
    }
    return calc();
  }
};
 
var result = numbers.sum();
console.log(result); // NaN
cs

numbers.sum()은 객체 내에 있는 메소드를 실행하는 것이기 때문에 sum 메소드 내의 문맥은 numbers 객체다.

즉, 5행에서 외부 함수의 thisnumbers인 것이다. 하지만 calc 함수는 sum 내부에 정의되었다. 이 때 thiswindow이다.

또한 이 때 9행에서 thiswindow이기 때문에 this.numAthis.numB가 각각 undefiend이므로 결과값은 NaN이 되는 것이다.

call, apply, bind로 해결할 수 있다.

이러한 문제를 해결하기 위해서 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() {
    console.log(this === numbers); // true
    function calc() {
      console.log(this === numbers); // true
      console.log(this === window); // false
      return this.numA + this.numB;
    }
    return calc.call(this);
  }
};
 
var result = numbers.sum();
console.log(result); // 15
cs

11행의 this는 외부 함수인 sum 메소드에 속하기 때문에 numbers이다.

calc.call(this)numbers 객체에 calc라는 메소드를 등록해주는 셈이기 때문에 calc 메소드의 thisnumbers가 된다.

call과 apply에 대한 더 자세한 설명은 여기에서 확인할 수 있다.



👋@Jess2
👩🏻‍💻Frontend Developer

GitHubFacebookLinkedIn