도리쓰에러쓰

[JavaScript] this란? 본문

JavaScript/JS

[JavaScript] this란?

강도리 2022. 8. 5. 17:07

자바스크립트에는 this라는 키워드가 있다.

this는 문맥에 따라서 다양한 값을 가지는데 this가 쓰이는 함수를 어떤 방식으로 실행하느냐에 따라서 그 역할이 구별된다.

this의 값들은 크게 4가지로 나눌 수 있는데 지금부터 알아보겠다.


1. 일반 함수 실행 방식 (Regular Function Call)

일반 함수 실행 방식(Regular Function Call)이란 아래 코드처럼 함수를 선언한 후, 실행할 때 흔히 사용하는 방식을 말한다.

일반 함수 실행 방식(Regular Function Call)으로 함수를 실행했을 때 this의 값은 Global Object 즉, 브라우저 상에서는 window 객체를 가리킨다. 

const example = () => {
  console.log(this);
}

example();

위 코드에서 example() 함수가 실행되고 콘솔에 this가 출력되는데

이 때, this는 글로벌 객체, 브라우저 상에서는 window의 객체를 가리킨다.

 

아래 코드는 전역 변수 place를 생성하고 'cafe'라는 값을 할당하였고 example() 함수에 this.place를 콘솔에 출력시킨 코드이다.

place는 전역 변수이기 때문에 전역 객체인 window에 속성으로 추가된다.

즉, 전역 변수 place에 'cafe'라는 값을 할당하면 window 객체에 place라는 key와 'cafe'라는 value가 추가된다.

그래서 this.place 값인 cafe가 콘솔창에 출력되는 것이다.

( 여기서 this는 window 객체를 가리키므로 this.place는 window.name이라고 한 것과 동일하다. )

const place = 'cafe';

const example = () => {
  console.log(this.place);
}

example();

 

아래 다른 예제 코드를 보자. 

const num = 1;

const example1 = () => {
  const num = 2;
  example2();
}

const example2 = () => {
  console.log(this.num);
}

example1();

이 코드는 example1() 함수 안에 example2() 함수가 실행되고 있고, example2() 함수는 this.num을 콘솔에 출력하는 코드이다.

이 때 this.num은 전역 변수로 선언된 1일까? example1()에 선언된 2일까?

다른 함수 안에 같은 변수명의 지역 변수를 선언하여도 this.num은 window.num을 가리키고, 이는 전역 변수로 선언된 num 변수의 값을 말한다. 그러므로 콘솔창에 출력되는 값은 1이다.


2. 도트 표기법 (Dot Notation)

도트 표기법 (Dot Notation)이란 우리가 객체를 만들고 그 객체의 key와 value를 부여한 후 도트(.)로 값에 접근하는 방식을 말한다. 아래 예제 코드를 보자.

const num = 1;

const a = {
  num: 2,
  example: function () {
    console.log(this.num);
  }
}

a.example();

a라는 변수에 객체가 있고 example라는 key에 this.num을 출력하는 함수가 있다.

a.example()라고 작성하여 함수를 실행하면 this는 그 도트(.) 앞에 작성한 객체를 가리킨다.

위 코드에서 this.num은 a를 가리키기 때문에 2가 출력된다.

 

아래 다른 예제 코드를 보자.

const example = () => {
  console.log(this.num);
}

const num = 1;

const a = {
  num: 2,
  example: example
}

const b = {
  num: 3,
  example: example
}

a.example(); // 2
b.example(); // 3

const aa = a.example;
aa(); // 1

위 예제는 example()이라는 함수가 있고 this.num을 출력하는 실행문이 있다.

그리고 전역 변수 num이 선언되고 1이라는 값이 할당되었다.

또 a라는 객체가 선언되어 num과 example이라는 key를 부여했고, example의 value는 함수 example()의 이름이다.

b도 a와 마찬가지로 객체가 선언되어 있다.

 

이 코드에서 a.example()라고 함수를 실행하면 도트 표기법 (Dot Notation) 방식으로 실행되었기 때문에 this는 a 라는 객체를 가리키게 되고 2란 값이 출력된다. b.example()라고 함수를 실행해도 마찬가지이다.

그러나  aa 변수를 보면 aa라는 변수에 a.example이라는 값을 입력하고 aa() 함수를 실행하였는데 1이 출력된다.

이는 도트 표기법 (Dot Notation) 방식이 아니고 일반 함수 실행 방식(Regular Function Call)으로 실행한 것이기 때문에 이 때의 this는 글로벌 객체를 가리키게 되고 전역 변수 num의 값인 1이 출력된다.


3. 명백한 바인딩 (Explicit Binding)

명백한 바인딩(Explicit Binding)은 this의 역할을 우리가 직접 명확하게 지정하는 것이다.

이는 function.prototype.call, function.prototype.bind, function.prototype.apply와 같은 메소드를 사용하여 할 수 있다.

 

const num = 1;

const example = () => {
  console.log(this.num);
}

const a = {
  num: 2,
  log: example
}

example.call(a, 5, 6, 7);

위 코드에서 example() 함수에 call 메소드를 사용했는데 인자로 a, 5, 6, 7을 주었다.

이 인자들 중에 첫번째로 쓴 a가 바로 this의 값으로 지정된다.

5, 6, 7은 this의 값과는 상관없이 순서대로 example()의 함수가 된다.

그러므로 this.num은 a.num이 되어 콘솔창에 2가 출력된다.


4. new 키워드를 사용한 함수 실행

new 키워드를 통해 함수를 생성자로 만들어 사용할 수 있다.

이 경우에 this는 빈 객체이다.

const example = () => {
  console.log(this);
}

new example();

위 코드에서 new 키워드를 사용하여 example() 함수를 생성자 함수로 사용했다.

이 때 this는 빈 객체를 가리키고, 생성자 함수는 this라는 빈 객체를 return한다.

💡 return문이 없어도 return한다. 생성자 함수의 특징 중 하나이다.

 

아래 다른 예제 코드를 보자.

const example = () => {
  console.log(this.num); // undefined
  this.num = 1;
  console.log(this.num); // 1
}

new example();

위 코드는 example() 함수가 생성자 함수로 사용되고 그 즉시, 함수 내부에 this는 빈 객체가 되며 this.num은 undefined가 된다.

그 빈 객체에 num이라는 속성을 추가하고 1이란 값을 할당하게 되면, this.num은 1을 출력하게 된다.

그리고 example() 함수는 { num: 1 } 이라는 객체를 리턴한다.

 

아래 또 다른 예제 코드를 보자.

const example = () => {
  this.num = 1;
  return 3;
}

const a = new example();
console.log(a);

생성자 함수는 특이하게 return문이 있어도 그 return문을 무시하고 this 객체를 return하는 특징이 있다.

그래서 위 코드에서 example() 함수는 일반적인 상식으로는 3이 리턴되야 하지만 생성자 함수이기 때문에 { num: 1 }이 리턴된다.

 

그러나 생성자 함수도 리턴되는 대상이 객체라면 this 객체 대신에 해당 객체가 리턴된다.

그래서 아래 코드를 확인해보면 a는 { num: 1 }이 아닌 { b: 1111 }가 된다.

const example = () => {
  this.num = 1;
  return { b: 1111 };
}

const a = new example();
console.log(a);

 

Comments