함께 성장하는 프로독학러

자바스크립트, this가 무엇이냐 본문

Programming/javascript

자바스크립트, this가 무엇이냐

프로독학러 2018. 4. 5. 16:29

안녕하세요, 프로독학러 입니다.


이번 포스팅에서는 직관적으로 이해하기 힘든 'this'란 녀석에 대해서 알아보도록 하겠습니다.


자바스크립트에서 this란 함수의 현재 실행 문맥을 의미합니다. 

실행 문맥이란 단어가 익숙하지 않으신 분들을 위해 첨언 하자면, '함수가 실행되는 객체'라고 이해하시면 될 것 같습니다.

전역에서 실행되고 있는 함수라면 전역객체 Window의 메소드가 실행 되는 것이므로 이때 함수의 this는 Window 객체 입니다.


this가 현재 함수의 실행 문맥이라 했는데, javascript에는 4가지의 함수 실행 타입이 있습니다.


  • 함수 실행 : alert('Hello world')
  • 메소드 실행 : console.log('Hello world')
  • 생성자 실행 : new RegExp("\d")
  • 간접 실행 : alert.call(undefined, 'Hello world')


이 각각의 실행 타입은 각자 서로 다른 문맥을 가집니다.


첫 번째 실행 타입인 함수의 실행은 전역에서 실행되는 함수이기 때문에 Window객체의 메소드로써 사용되는 것과 같습니다.

따라서 함수의 실행 타입에서의 this는 Window입니다.

//하지만 엄격모드(함수 내부의 최상단에 'use strict' 라는 예약어를 사용한 함수)에서 this는 undefined입니다. Window로 간주되는 것을 막습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function nonStrictSum(a, b) {  
  // 비 엄격 모드
  console.log(this === window); // => true
  return a + b;
}
function strictSum(a, b) {  
  'use strict';
  // 엄격 모드
  console.log(this === undefined); // => true
  return a + b;
}
// nonStrictSum() 함수는 비 엄격 모드로 실행
// nonStrictSum()에서의 this는 window 객체
nonStrictSum(56); // => 11  
// strictSum() 함수는 엄격 모드로 실행
// strictSum()에서의 this는 undefined
strictSum(812); // => 20  
cs


위의 예제를 통해 함수의 실행에서의 this에 대해서 살펴볼 수 있습니다.


두 번째 실행 타입인 메소드 실행은 메소드가 정의된 객체를 this로 가집니다.


1
2
3
4
5
6
7
8
9
10
11
var calc = {  
  num: 0,
  increment: function() {
    console.log(this === calc); // => true
    this.num += 1;
    return this.num;
  }
};
// 메소드 실행. 여기서의 this는 calc.
calc.increment(); // => 1  
calc.increment(); // => 2
cs


위의 예제에서 calc라는 객체 안의 'increment' key에 value로 함수가 할당 돼 있는것을 볼 수 있습니다.

즉, 이는 calc객체의 메소드 입니다. 따라서 increment함수의 this는 메소드가 정의돼 있는 객체(clac)인 것을 알 수 있습니다.


세 번째 실행 타입인 생성자를 실행 할 때의 this는 새롭게 만들어질 객체를 의미합니다.

생성자 함수는 함수가 실행될 때, 생성자 함수를 정의한 단계에서의 설정에 따라 새로운 객체를 만드는 것을 의미합니다.


1
2
3
4
5
6
7
function Foo () {  
  console.log(this instanceof Foo); // => true
  this.property = 'Default Value';
}
// 생성자 실행
var fooInstance = new Foo();  
fooInstance.property; // => 'Default Value'
cs


위의 예제에서 Foo함수는 생성자 함수입니다. Foo함수를 호출해 새로운 객체를 만들 때, 새롭게 만들어지는 객체에 property라는 key에 'Default Value'라는 값을 할당하겠다고 선언되어 있습니다.

따라서 아래에서 생성자 함수를 실행해 생성된 객체를 fooInstace라는 변수에 담았습니다.

fooInstance 객체에 property라는 속성을 부여한 적은 없지만, 생성자함수에서 미리 만들어질 객체(this)에 부여했으므로 property속성이 존재하는 것입니다.


네 번째 실행 타입인 간접실행(call 메서드나 apply 메서드와 함께 함수가 호출 되는 것)에서의 this는 call, apply메서드의 첫 번째 인자입니다.

즉, 간접실행은 this를 지정해주는 것입니다.


1
2
3
4
5
6
7
8
var rabbit = { name'White Rabbit' };  
function concatName(string) {  
  console.log(this === rabbit); // => true
  return string + this.name;
}
// Indirect invocations
concatName.call(rabbit, 'Hello ');  // => 'Hello White Rabbit'  
concatName.apply(rabbit, ['Bye ']); // => 'Bye White Rabbit'
cs


위의 예제의 첫 번째 줄에서 rabbit이라는 객체를 정의했습니다.

그리고 그 아랫줄에서 concatName이라는 함수를 정의 했습니다. 이 함수는 인자로 들어온 값(문자)과 해당 함수의 문맥의 name속성을 더해 리턴합니다.

맨 밑의 두 줄에서는 concatName함수를 call메서드와 apply메서드를 이용해 간접 실행 합니다.

두 메서드의 방식 모두 this값을 rabbit객체로 지정했기 때문에 rabbit.name값을 활용해 문제없이 리턴하는 것을 볼 수 있습니다.

만약, 함수를 간접실행하지 않고, 직접실행했다면 (concatName('Hello'); 와 같이) this는 Window객체를 의미하므로 Window객체에서 name 속성을 찾지 'Hello' 만 리턴될 겁니다.


정리하자면, 자바스크립트에서 this는 함수의 실행 방식에 따라 달라집니다.


this는...

함수를 실행 할 때는 전역객체인 Window객체(엄격모드에선 undefined),

메소드를 실행 할 때는 메소드를 정의한 객체,

생성자를 실행 할 때는 새롭게 만들어질 객체,

간접실행 할 때는 call, apply메서드의 첫 번째 인자로 들어오는 객체

입니다.


제 관점에서 적은 글이라 설명이 부족하다 느끼실수도, 빈약하다 느끼실 수도 있겠지만 모쪼록 읽는 분들에게 도움이 됐으면 좋겠습니다.

감사합니다.


** 참고자료

https://github.com/FEDevelopers/tech.description/wiki/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%EB%90%98%EB%8A%94-this%EC%97%90-%EB%8C%80%ED%95%9C-%EC%84%A4%EB%AA%85-1#1-this%EC%97%90-%EB%8C%80%ED%95%9C-%EB%AF%B8%EC%8A%A4%ED%84%B0%EB%A6%AC


*다녀가셨다는 표시는 공감으로 부탁드릴게요! (로그인 하지 않으셔도 공감은 가능합니다 ㅎㅎ)


'Programming > javascript' 카테고리의 다른 글

배열과 문자열의 indexOf 메서드  (0) 2018.04.09
배열의 sort 메서드  (1) 2018.04.09
배열의 reduce 메서드  (0) 2018.04.05
배열의 map 메서드  (0) 2018.04.03
자바스크립트의 비동기 작업 처리방식  (1) 2018.04.03
Comments