ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 - this?!
    JavaScript/기본 2020. 9. 3. 15:42

     

     

    들어가기 전에, 

    먼저 대표적으로 JAVA 같은 객체지향 언어에서의 this는 클래스 인스턴스의 레퍼런스 변수를 말한다.

    즉, 클래스(자세히는 인스턴스화 된 객체) 자기 자신을 뜻 한다는 의미이다.

    하지만 자바스크립트에서 함수의 this 키워드는 다른 언어들과 비교하여 조금 다르게 동작한다.

    다르게 동작하기 때문에 많이 헷갈리는 것 같다.

    자바스크립트에서는 선언할 때 값이 결정되는 것이 있는데 그것을 클로져라고 하고, 반면에 호출하는 방법에 의해서 값이 결정되는 것이 있는데 그것을 바로 this라고 한다.

    그 this를 낱낱이 파헤쳐보도록 하자.

     

    this는 대체 무엇인가?

    할머니 : 나는 허리가 아프다. (나 === 👵)

    아버지 : 나는 다리가 아프다. (나 === 👨)

    어머니 : 나는 머리가 아프다. (나 === 👩‍🦱)

    자바스크립트에서 this란 위의 문장들에서 나타난 '나'라는 단어와 비슷하다.

    즉, this는 현재 실행 문맥을 말하며, 실행 문맥이란 말은 호출자가 누구냐는 것과 같다.

    한마디로, 호출한 놈(객체) === this라는 뜻이다.

     

    this를 어떻게?

    예제를 통해 확인해보자.

    const someone = {
        name: "Lim",
        whoAmI: function(){
        	console.log(this);
        }
    }
    
    someone.whoAmI(); // 출력 : {name: "Lim", whoAmI: ƒ}
    
    const myWhoAmI = someone.whoAmI;
    myWhoAmI(); // 출력 : Window

    someone.whoAmI()는 예상한 대로 someone 객체 값이 출력이 되었지만, myWhoAmI()의 출력 값은 Window였다. 보자마자 뭐지..? 딱 이거였다.

    일단 처음에 출력 결과를 보고 도저히 이해할 수가 없었다.

    왜냐하면, someone.whoAmI()와 myWhoAmI()는 똑같이 someone 객체를 가지고 있기 때문이다.

    그렇다면 왜 값이 다른 것인가?

    그 이유는 바로 호출하는 방법이 달라졌기 때문이다.

    this는 호출하는 방법에 따라 결정되는데, 그 this가 달라졌기 때문에 값이 달라진 것이다.

    그럼 그 this를 어떻게 아느냐? 이렇게 묻는다면, 정답은 호출을 어떻게, 누가 했느냐?이다.

    먼저 someone.whoAmI();

    이 부분을 살펴보면, whoAmI()를 호출한 직접적인 아이는 바로 someone이다.

    즉, someone에서 whoAmI()를 꺼냈기 때문에 this는 someone이 되는 것이다.

    반면 myWhoAmI();

    myWhoAmI()는 직접적으로 호출한 아이는 바로 전역 스코프에 위치해 있기 때문에, 전역 객체 window이다.

    즉, myWhoAmI()는 전역에 위치해 있고 window가 myWhoAmI()를 실행시켰기 때문에 this는 window가 되는 것이다.

     

    하지만 예외적인 방법 존재!

    그것은 바로 bind 메서드

    bind란?

    ES5에서 함수의 this 값이 함수가 어떻게 호출되었는지 개의치 않고 설정할 수 있는 메서드를 말한다.

    즉, 호출되는 방법 무관하게 this를 고정시키는 것을 말한다.

    예제를 살펴보자.

    const someone = {
        name: "Lim",
        whoAmI: function(){
        	console.log(this);
        }
    }
    
    someone.whoAmI(); // 출력 : {name: "Lim", whoAmI: ƒ}
    
    const myWhoAmI = someone.whoAmI;
    myWhoAmI(); // 출력 : Window
    
    const bindedWhoAmI = myWhoAmI.bind(someone);
    bindedWhoAmI(); // 출력 : {name: "Lim", whoAmI: ƒ}

    위 예제의 결과를 보면 전역 범위에서 myWhoAmI()와 bindedWhoAmI()가 호출되는 것을 볼 수 있다.

    그렇다면 분명 결과값은 myWhoAmI()처럼 window가 나와야 하는데 bindedWhoAmI()의 결과 값은 someone을 출력하고 있다.

    그 이유는 바로 bind 때문이다.

    const bindedWhoAmI = myWhoAmI.bind(someone);

    이 구문의 의미는 someone을 무조건 this로 하겠다는 의미이다.

    즉, 호출하는 방법은 같으나 예외적으로 bind라는 것에 묶였기 때문에, 무조건 묶인 것이 this라는 뜻이다.

    그 외에는 다 누가 호출했는지에 결정된다.

    추가적으로 bind() 이외에도 call(), apply() 메서드 또한 같은 역할을 한다.

    call()과 apply()는 함수들이 가지고 있는 메소드들인데, 이 메소드를 써서 함수를 실행시킬 수 있는 것을 말한다.

    이처럼, bind, call, apply을 통해 함수를 호출하게 되면, this가 어떤 문맥을 사용할지, 내가 컨트롤할 수 있게 된다.

     

    Function.prototype.apply()

    apply() 메서드는 주어진 this 값과 배열 (또는 유사 배열 객체) 로 제공되는 arguments 로 함수를 호출합니다.

    developer.mozilla.org

     

    Function.prototype.call()

    call() 메소드는 주어진 this 값 및 각각 전달된 인수와 함께 함수를 호출합니다.

    developer.mozilla.org

     

    🎈 정리

    자바스크립트에서는 선언할 때 결정되는 것이 있고, 호출할 때 결정되는 것이 있다.

    this가 바로 호출할 때 결정되는 것이고, 그 this는 호출한 놈, 호출한 객체가 바로 this라는 것이다.

    그리고 그 this를 호출과 무관하게 고정시켜 줄 수 있는 아이가 바로 bind라는 메서드이다.

    이 bind라는 함수를 이용해서 묶어주면 this는 호출과 무관하게 고정된다.

    bind 이외에도 call, apply 메서드 또한 같은 역할을 수행한다.

     

    참고!

    아직 this에 대해 공부할 부분들이 많아서 더 공부해서 내용을 채울 예정이다.

    댓글

Designed by Tistory.