본문 바로가기
📌 Front End/└ JavaScript

[JavaScript] 자바스크립트 this란?

by 쫄리_ 2023. 3. 10.
728x90
반응형

C++, JAVA와 같은 언어에서 this는 자기자신 객체를 가리킨다.
그러나 JavaScript 의 this 값은 실행 컨텍스트의 thisValue 에 의해 값이 바인딩 된다.

thisValue는 아래의 5가지 패턴에 의해 결정된다.

  • 전역(global)
  • 함수 호출(function Invocation)과 메서드 호출(Method Invocation)
  • call(), apply(), bind()
  • 생성자(Construction)
  • strict 모드

💡 바인딩 : 실제 값이 변수에 묶이는 것
💡 strict 모드 : ES5 에 있는 새로운 기능으로 엄격하게 문법을 검사하는 모드이다.


1. 전역(global)

전역에서 this는 전역 컨텍스트의 영향을 받아 this 값은 전역 객체 가 된다.

// 브라우저에서는 window 가 전역객체 이다.
console.log(this === window);           // true

this.myString = "hello?";
console.log(window.myString);           // "hello?" 
console.log(myString);                  // 전역 변수 myString을 출력: "hello?" 

💡 NodeJS 의 경우, 전역에서의 this 값은 global 이 된다.


2. 함수 호출과 메서드 호출

함수 내부의 this 값은 함수의 호출 방식에 따라서 결정된다.

단순하게 메서드나, 내부함수, 콜백함수를 호출하는 경우 this 는 전역 객체 에 바인딩된다.

function foo() {
  console.log("foo's this: ",  this);    // Window
  function bar() {
    console.log("bar's this: ", this);   // Window
  }
  bar();
}
foo();

그러나 객체 리터럴 안에서 this는 자기 자신에게 바인딩된다.
하지만 메서드의 내부 함수는 전역 객체에 this 값이 바인딩 된다.

var value = 1;

const obj = {
  value: 100,
  qux: function() {
     console.log(this.value);         // this === obj, 100 출력
     setTimeout(
       // 메서드의 내부 함수
       function() {
         console.log(this);           // this === Window, Window 출력
         console.log(this.value);     // 1 출력
       }, 0);
  }
}

obj.qux();

3. call(), apply(), bind()

call(), apply(), bind() 사용하여 this 값을 설정할 수 있다.

  • call(): 이미 할당되어 있는 다른 객체의 함수/메서드를 호출하는 해당 객체에 재할당할 때 사용
  • apply(): call() 과 비슷하나 인수들을 단일 배열로 받는다.
  • bind(): this 값이 바인딩 된 새로운 함수를 반환한다.
var value = 20;

function mySum(num) {
  // this.value 가 없는 경우
  if(this.value == undefined) this.value = 50;

  return this.value + num;
}

// this 값을 따로 지정하지 않아 global 객체(window)가 this가 됨
console.log(mySum(2));                  // 22

// call()
console.log(mySum.call(mySum, 2));      // 52

// apply()
console.log(mySum.apply(mySum, [9]));   // 59

// bind()
var bindMySum = mySum.bind(mySum);
console.log(bindMySum(50));             // 100

4. 생성자(Construction)

생성자를 사용하는 경우로new 연산자, class의 constructor를 사용하는 경우 this 바인딩이 자기 자신으로 된다.

function test(number) {
    this.num = number;
}

// new 연산자를 사용하여 생성
var obj = new test(1);
console.log(obj.num);        // 1

/* ================ 만약에 new 를 사용하여 obj를 선언하지 않은 경우 ================ */
// 함수내에서 this.num 은 window.num 으로 바인딩 된다.
console.log(obj.num);        // Uncaught TypeError

생성자를 통해 함수를 호출하면 다음과 같은 과정으로 동작한다.

  1. 빈 객체 생성 및 this 바인딩
    • 함수 생성전 빈 객체를 생성함(이때 this가 이 객체를 가리킴)
    • 생성된 빈 객체는 생성자 함수의 prototype 을 자신의 prototype 으로 설정함
  2. this.메서드, this.속성 등 this를 통해 생성한 속성와 메서드는 새로 생성된 객체에 추가함
  3. 생성된 객체를 반환
    • 반환문(return)이 없으면 암묵적으로 생성된 객체를 반환
    • 반환문에 this 가 아닌 다른 객체를 반환하는 경우 해당 객체가 반환됨
function Obj(num) {
  // 생성자 함수 코드 실행 전 ---------- 1
  this.num= num;         // ---------- 2
  // 생성된 함수 반환 ------------------3
}

var me = new Obj(33);
console.log(me.num);

따라서, new 연산자를 사용하지 않고 함수로 객체를 만드는 경우
객체를 암묵적으로 생성하여 반환하지 않으며 this는 전역 객체 를 가리킨다.

📖 객체 리터럴 vs 함수

객체 리터럴 방식과 함수 방식의 차이는 [[Prototype]](프로토타입 객체) 에 있다.

> // 객체 리터럴 방식
> // [[Prototype]] : Object.prototype
> var obj = {
>     name: "dulli",
>     age: 100
> }
> 
> // 함수 방식
> // [[Prototype]] : obj.prototype
> function obj2() {
>     this.name: "ddochi",
>     age: 35
> }
> var objIns = new obj2();
> 

5. strict 모드

strict 모드 라면 this 값은 undefined 가 된다.

// 함수 내에서 use strict 모드 활성화 
function test() {
  "use strict";
  return this;         // 여기서 this는 undefined
}

console.log(this);     // Window, 전역 객체
console.log(test());   // undefined

결론

JavaScript에서는 this 값은 실행 컨텍스트의 thisValue 에 의해 값이 바인딩 된다.
thisValue 는 아래의 5가지 패턴에 의해 결정이된다.

  • 전역(global) : this === 전역객체
  • 함수 호출(function Invocation)과 메서드 호출(Method Invocation)
    • 단순한 함수 호출 : this === 전역객체
    • 객체 리터럴(메서드 호출);
      • 메서드안에서 this === 자기자신
      • 메서드의 내부 함수의 this === 전역객체
  • call(), apply(), bind() : this 값이 매개변수에 바인딩됨
  • 생성자(Construction) : this === 자기자신
  • strict 모드 : this === undefined

참조

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this
https://hyunseob.github.io/2016/03/10/javascript-this/
https://muckycode.blogspot.com/2015/04/javascript-this.html
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/애로우_펑션

728x90
반응형