{Es6} this에 대해서 알아보자.

특급한라봉·2023년 3월 2일
0

Javascript Deep

목록 보기
1/8
post-thumbnail

비전공자로써 자바스크립트를 처음 공부했던 저에게 가장 어려웠던 문법 중 하나를 꼽으라고 한다면, 바로 this 문법 입니다. this는 어떤 방식으로 불러내는지에 따라 코드의 해석이 달라지는 특징이 있습니다.

저는 코린이 시절 this를 사용할때면 명확한 용도를 알고 사용하는 것이 아니라 아리까리한 개념으로 사용을 했기 때문에 this를 사용하기가 상당히 껄끄러웠던 경험이 있었습니다.

혹시나 저와 같이 this의 정확한 쓰임에 대해서 헷갈려하시는 분들을 위해 오늘은 바로 이 this에 대해서 정리를 해볼까 합니다.

누가 날 부르는가???

대부분의 경우 this의 값은 함수를 호출한 방법에 의해 결정됩니다. 실행중에는 할당으로 설정할 수 없고 함수를 호출할 때 마다 다를 수 있습니다. ES5는 함수를 어떻게 호출했는지 상관하지 않고 this 값을 설정할 수 있는 bind 메서드를 도입했고, ES2015는 스스로의 this 바인딩을 제공하지 않는 화살표 함수를 추가했습니다(이는 렉시컬 컨텍스트안의 this값을 유지합니다).

위 내용은 MDN에서 발췌해온 this에 대한 내용입니다. 굳이 해석하실 필요가 없습니다. 위 발췌 글에서

"대부분의 경우 this의 값은 함수를 호출한 방법에 의해 결정됩니다."

위 문장만 알고가면 되겠습니다. 위 문장을 조금 더 쉽게 설명하자면 this를 어떤 방식으로 불러내는지 에 따라 4가지로 해석이 가능합니다. 해석 방법이 하나, 둘, 셋도 아니고 네 가지나 된다고? 쫄거 없습니다. 순서대로 하나씩 알아봅시다.

1. 전역에서 this.

예시1. 전역에서 this

    
    console.log(this);	//window
    

당장 여러분이 vscode를 켜서 HTML 문서를 하나 만들고 script 영역에서 this를 불러내면 "window" 라는 값이 등장합니다. 전역범위에 this는 바로 window입니다.

그렇다면 함수 내부에서 this는 어떤 값을 출력할까요?

예시2. 함수에서 this


  let 함수 = function(){
        console.log(this);	//window
  }

  함수();

딱히 함수라고 해서 특별할건 없습니다. 마찬가지로 함수로 불러낸 this 역시 window를 가르킵니다.

window???
window란 전역변수, 함수, DOM 등등 모든 요소들을 보관하고 관리하는 최상위 '전역객체' 입니다.
즉, 쉽게 말해서 window는 커다란 '보관소' 입니다. 우리가 script 영역 내에서 변수를 만들면 바로 이 window에 보관됩니다. 그래서 script 영역에서 만든 변수를 "전역변수" 라고 합니다. (함수 안에서 만들어진 변수들은 "지역변수" 라고 하며 이 지역변수는 window에 보관되지 않습니다. )

  Document.getElementById(''), 
  console.log(), 
  alert(), 
  //기타 등등등...

또한, 여러분들이 평소 자주 사용하는 위의 함수들은 자바스크립트에 내장되어 있는 '내장함수' 로, window는 이런 무수히 많은 내장 함수들을 보관하고 있습니다.


2. 객체에서 this.

우리가 평소 자주 사용하는 함수를 객체 안에서도 만들 수 있다는거 알고 계신가요? 객체 안에서 만들어진 함수는 함수라고 부르지 않고 "메소드(method)" 라는 용어가 더 정확합니다. 이 객체 메소드 내부에서 this를 불러내면 어떤 값이 나올까요?

예시3. 객체 메소드에서 this


  let 아이유 = {
      name: "이지은",

      method(){
          console.log(this);	//아이유
      }
  };

  아이유.method();
  

콘솔에서 {name: "이지은", method: function} 이런 값이 출력 됐다면 성공입니다. 이 값은 곧 우리가 만든 "아이유" 이라는 객체입니다.

그렇습니다, 메소드 내부에서 this는 상위 객체를 지칭합니다. 즉, 아이유 객체 메소드 안에서 this는 곧 아이유 객체 자체를 말합니다.

예시4. 객체 메소드 내부 함수에서 this


  let 아이유 = {
    name: "이지은",

    sayHi(){
        function getName(){
        	return `안녕하세요. ${this.name} 입니다.`
        }
        console.log(getName())
    }
};

아이유.sayHi();	//안녕하세요.  입니다.
  

그렇다면 객체 메소드에서 한번 더 함수를 만들어서 this를 불러내면 어떻게 해석이 될까요? 이 경우 출력되는 값은 window 입니다.

"어?! 객체 메소드에서 this는 객체 그 자체라면서요!!!"

맞습니다. 하지만! 객체 메소드의 내부 함수는 자바스크립트가 메소드가 아닌 단순 함수로 인식합니다. 예시2에서 함수에서 불러낸 this는 window를 가르킨다고 했었죠? 그것과 같습니다.

예시5. bind(), call(), apply()를 이용하자.


  let 아이유 = {
    name: "이지은",

    sayHi(){
        function getName(){
        	return this.name
        }
        console.log(getName.bind(this).call())
        console.log(getName.call(this))
        console.log(getName.apply(this))
      }
  };

아이유.sayHi();

만약 함수안에서 this를 불러내서 사용하고 싶다면 bind(), call(), apply() 세가지 함수를 사용하시면 됩니다. 이 세가지 함수를 사용하면 this가 객체를 지칭하도록 할 수 있습니다. 각각의 함수를 필요에 맞게 사용하시면 되겠습니다.


3. 이벤트리스너에서 this.

예시6. 이벤트리스너에서 this


	<button>버튼이다</button>
   
   
	document.querySelectorAll('button').addEventListener("click", function(){
		console.log(this);    
  	}

HTML에 버튼 태그를 하나 만들었습니다. 그리고 이 버튼에 script 상에서 이벤트리스너를 사용해 this라는 값을 불러낼 수 있는 기능을 추가했습니다.

이벤트리스너로 불러낸 this는 이벤트리스너가 부착된 대상을 지칭합니다. 즉, this는 버튼 그 자체를 의미합니다. 우리가 만든 버튼을 window 상에서 클릭해 보면 버튼 태그 내부에 적혀있는 "버튼이다" 라는 값이 콘솔에 출력됩니다.


4. 생생자 함수에서 this.

간략하게 설명하자면, 생성자 함수(constructor)란 객체를 한번에 많이 만들기 위해 사용하는 함수입니다. 붕어빵틀이라고 이해하면 쉽습니다.

아래 예시7에 "붕어빵틀" 이라는 생성자 함수를 하나 만들었고 그 아래 붕어빵 1부터 3까지 순식간에 객체 3개를 찍어냈습니다. 생성자 함수를 이용해서 객체를 찍어낼 땐 꼭 "new" 라는 키워드를 함께 사용해야 합니다.

또한, 생성자 함수를 통해 만들어진 객체들을 조금 더 정확하게 지칭하자면 "인스턴스(instance)" 라고 합니다. 붕어빵1~3들이 붕어빵틀의 인스턴스들 입니다.

예시7. 생생자 함수에서 this


	function 붕어빵틀(이름, 재료){ 	//생성자 함수 선언
      this.이름 = 이름;
      this.재료 = 재료;
    };

    let 붕어빵1 = new 붕어빵틀("붕어싸만코1", "팥");
    let 붕어빵2 = new 붕어빵틀("붕어싸만코2", "슈크림");
    let 붕어빵3 = new 붕어빵틀("붕어싸만코3", "불닭");
	//생성자 함수로 만들어진 인스턴스

    console.log(붕어빵1, 붕어빵2, 붕어빵3);
    

자, 생성자 함수에 사용된 this가 보일겁니다. 여기서 this는 생성자 함수를 통해 불러낸 인스턴스들을 뜻합니다. 붕어빵틀이라는 생성자 함수가 붕어빵1~3을 만들때 각각의 이름과 재료(파라미터)들을 this를 사용해 인자값으로 받았기 때문입니다.


화살표 함수를 사용해보자!

화살표 함수(Arrow function)란 ECMAscript 6에 추가된 신문법입니다. 화살표 함수는 기존의 함수를 축약해서 사용할 수 있는 장점이 있습니다.

이 화살표 함수가 this 와 무슨 연관이 있을까요??? 위에서 우리는 this가 불러내는 방법에 따라 내부 값이 변한다는 특징에 대해서 알아봤습니다.

하지만 화살표 함수를 사용하면 this 값이 변하는 것을 막을 수 있습니다. 이렇게 좋은 기능이 있었다고? 당장 예시로 알아보겠습니다.

예시8. 화살표 함수에서 this I


  let 아이유 = {
      name:'이지은',

      sayHi(){
          let getName = (() => {
              return `안녕하세요. ${this.name} 입니다.`;
          }) 
          console.log(getName());
      }
  }
  아이유.sayHi(); 	// 안녕하세요. 이지은 입니다.
    

화살표 함수는 함수를 만들때 function 대신 =>(화살표)를 사용합니다. 기존의 함수를 축약형으로 사용할 수 있다는 이점이 있습니다.

예시4와 비교해보면 객체 메소드 내부 함수로 불러낸 this는 window를 지칭한다고 했습니다. 하지만 화살표 함수는 상위의 this를 그대로 내부로 가져올 수 있습니다. 함수 하나 바꿨을 뿐인데 다른 값이 출력이 되는군요???

하지만! 화살표 함수의 이런 특징이 항상 장점이라고 할 수 없습니다.

예시9. 화살표 함수에서 this II


  let 아이유 = {
      name:"이지은",

      sayHi: (() => {
          console.log(`안녕하세요. ${this.name} 입니다.`)
      }) 
  }

  아이유.sayHi()
    

상위의 this를 그대로 가져온다는 화살표 함수의 특성상, 예시9의 경우 아이유라는 객체의 상위 this를 가져오게 됩니다.

"엥?? 객체 범위를 뛰어넘는 더 상위의 this???"

이거 어디서 본 개념이네요? 네 맞습니다. 바로 window 입니다. 예시1에서 전역에서 불러낸 this는 window를 지칭한다고 했었죠? 이처럼 화살표 함수를 사용해서 this를 잘못 불러내면 엉뚱한 window가 튀어 나올 수 있으니 주의해서 사용해야 합니다.


정리

this는 불러내는 방법에 따라 크게 4가지로 해석이 가능.
1. 전역범위, 함수 → window
2. 객체 메소드 → 객체 그 자체
3. 이벤트리스너 → 이벤트리스너가 지칭하는 대상
4. 생성자 함수 → 인스턴스

화살표 함수를 사용하면 상위의 this를 내부에 불러올 수 있지만 상황에 맞게 사용해야함.
1. 객체 메소드 내부 함수 → 객체 그 자체
2. 객체 메소드 → window

this에 대해서 알아보자 끝.

profile
쉽게 쉽게 가자

0개의 댓글