ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [코어 자바스크립트] this
    Javascript 2024. 2. 22. 22:51

    대부분의 객체지향 언어에서 this는 클래스로 생성한 인스턴스 객체를 의미한다. 따라서, 혼란의 여지가 없거나 많지 않은데 자바스크립트 에서는 this는 어디서든 사용할 수 있다. 또한 상황에 따라 this가 바라보는 대상이 달라지는데 어떤 이유로 그렇게 되는지를 파악하기 힘든 경우도 있고 예상과 다르게 엉뚱한 대상을 바라보는 경우도 있다.

    함수와 객체(메서드)의 구분이 느슨한 자바스크립트에서 this는 실질적으로 이 둘을 구분하는 거의 유일한 기능이다.

     

    상황에 따라 달라지는 this

    자바스크립트에서 this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정된다. 즉, this는 함수를 호출할 때 결정된다는 말이다.

    전역 공간에서의 this

    전역 공간에서의 this는 전역 객체를 바라본다. 개념상 전역 컨텍스트를 생성하는 주체가 바로 전역 객체이기 떄문이다.

    브라우저 환경에서의 전역 객체는 window이고, Node.js 환경에서는 global이다.

    메서드로서 호출할 때 그 메서드 내부에서의 this

    함수 vs 메서드

    함수와 메서드를 구분하는 유일한 차이는 독립성에 있다. 함수는 그 자체로 독립적인 기능을 수행하는 반면, 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행한다. 자바스크립트는 상황별로 this 키워드에 다른 값을 부여하게 함으로써 이를 구현했다.

    메서드 내부에서의 this

    호출 주체는 함수명 앞의 객체이다. 즉, 점 표기법에서 점 앞에 명시된 객체 this.

    함수로서 호출할 때 그 함수 내부에서의 this

    함수 내부에서의 this

    어떤 함수를 함수로서 호출한 경우에는 this가 지정되지 않는다. 즉, 이때 this는 전역 객체를 바라본다.

    메서드의 내부 함수에서 this를 우회하는 방법

    '변수를 활용하는 활용하는 것'이다. 상위 스코프의 this를 저장해서 사용하는 방식으로 주로 self와 같은 식별자로 변수에 저장하여 this를 우회하여 사용한다.

    콜백 함수 내부에서의 this

    해당 콜백 함수의 제어권을 넘겨받은 함수가 정의한 바에 따르며, 정의하지 않은 경우에는 전역객체를 참조한다.

    생성자 함수에서의 this

    생성될 인스턴스를 참조한다.

     

    명시적으로 this 바인딩 하기

    기본적으로 함수로서 호출하면 this는 전역객체를 참조하고, 메서드로서 호출하면 this는 호출한 객체를 참조하게 된다.

    명시적으로 임의의 객체를 this로 지정할 수 있는 방법이 있다.

    call, apply 메서드 활용

    1. 함수로서 호출

    let func = function (a, b, c) {
      console.log(this, a, b, c);
    };
    
    func(1, 2, 3);                          // 전역객체 window  1 2 3
    func.call({ x: 'test' }, 1, 2, 3);      // { x: 'test' } 1 2 3  
    func.apply({ x: 'test' }, [1, 2, 3]);   // { x: 'test' } 1 2 3
    
    /* 명시적으로 this에 { x: 'test' }객체를 지정할 수 있다! */

     

    2. 메서드로서 호출

    let obj = {
      method: function (x, y) {
        console.log(this, x, y);
      }
    };
    
    obj.method(1,2);                         // obj 1 2
    obj.method.call({ x: 'test'}, 1, 2);     // { x: 'test' } 1 2
    obj.method.apply({ x: 'test'}, [1, 2]);  // { x: 'test' } 1 2
    
    /* 명시적으로 this에 { x: 'test' }객체를 지정할 수 있다! */

     

    3. 유사배열객체에 배열메서드 적용

    유사배열 객체란? 키가 0 또는 양의 정수인 프로퍼티가 존재하고 length 프로퍼티의 값이 0 또는 양의 정수인 객체.

    즉, NodeList 등과 같이 []로 감싸져있는 녀석들은 배열이 아니라 객체이다. 따라서, 배열의 메서드를 적용할 수 없으나, call / apply를 통하여 배열의 메서드를 적용할 수 있는 방법이 있다.

    /* 유사 배열 객체 */
    let arr_Obj = {
      0: 'one',
      1: 'two',
      length: 2
    };
    
    Array.prototype.push.call(arr_Obj, 'three');
    console.log(arr_Obj);     // { '0': 'one', '1': 'two', '2': 'three', length: 3 }
    
    /* slice는 매개변수를 아무것도 넘기지 않을 경우, 원본 배열의 얕은 복사 */
    let changeArr = Array.prototype.slice.call(arr_Obj);
    console.log(changeArr);   // [ 'one', 'two', 'three' ]
    /* 함수 내부에서 접근할 수 있는 arguments 객체도 유사배열객체 */
    function innerfunc() {
      console.log(arguments);
    };
    innerfunc('a','b');    // { '0': 'a', '1': 'b', length: 2}
    
    
    function argu() {
      let change = Array.prototype.slice.call(arguments);
      console.log(change);
    };
    argu(1,2,3);           // [1, 2, 3]

     

    4. 문자열에 배열메서드 적용

    유사배열 객체 뿐만 아니라, 문자열에도 배열 메서드를 call / apply를 이용해서 적용할 수 있는 방법이 있다.

    적용가능한 배열 메서드는 every, some, map, reduce 등이 있다.

    let str = 'string';
    
    Array.prototype.every.call(str, function(char) {
      return char !== ''
    });                      // false
    
    Array.prototype.some.call(str, function(char) {
      return char === ''
    });                      // true
    
    let strToArr = Array.prototype.map.call(str, function(char) {
      return char
    });
    console.log(strToArr);   // ['s','t','r','i','n','g']
    
    let newStr = Array.prototype.reduce.call(str, function(acc, cur, idx) {
      return acc + cur + idx  },'');
    console.log(newStr)      // 's0t1r2i3n4g5'

     

    5. 유사배열객체 + 문자열을 배열로 전환 (ES6)

    ES6에서는 유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환하는 Array.from 메서드를 새로 도입하였다.

    let obj = {
      0: 'a',
      1: 'b',
      2: 'c',
      length: 3
    };
    let newArr = Array.from(obj);
    console.log(newArr);             // [ 'a', 'b', 'c' ]

     

    bind 메서드

    this 및 함수에 넘길 인수를 일부 지정해서 새로운 함수를 만든다.

     

     

     

     

    * 정리하며 다시 스스로 생각해볼 질문

    1. 자바스크립트에서 this는 언제, 어떻게 결정되나요?

    2. 함수와 메서드의 차이와 내부에서 this는 어떻게 활용되고 있나요?

    3. 콜백함수 내부에서 this는 어떻게 동작하는지 설명해주세요.

    4. 유사배열 객체는 call / apply를 이용해서 어떻게 활용할 수 있나요?

     

     

    [참조]

    https://whoyoung90.tistory.com/23

Designed by Tistory.