[JS] JavaScript에서 다양한 this

    반응형

    JavaScript에서 this

    JavaScript에서 this객체를 가르키는 키워드로, 현재 실행 중인 함수의 문맥(context)을 가르킨다.

    this가 가르키는 대상은 함수 호출 방식에 따라 달라진다.


    01) 전역 범위

    • 전역 범위에서 this는 기본값으로 전역 객체를 의미
    • 브라우저에서 전역 객체는 window 객체로, 브라우저 환경에서 제공되는 다양한 API를 제어할 수 있음
    console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}

     

    02) 함수 호출

    • 일반 함수에서 this는 기본적으로 전역 객체를 가리킴
    • 호출한 객체가 없으므로 window 객체가 출력됨
    function printThis() {
      console.log(this);
    }
    printThis(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}

     

    03) 메서드 호출

    • 객체 안에서 메서드를 호출할 때, this는 해당 객체(=person)를 가리킴
    let person = {
      name: "peazh",
      age: 20,
      printThis: function () {
        console.log(this);
      },
    };
    person.printThis(); // { name: "peazh", age: 20, hello: f }
    function printThis() {
      console.log(this);
    }
    
    let person1 = {
      name: "여름1",
      printThis: printThis,
    };
    person1.printThis(); // {name: '여름1', printThis: ƒ}
    
    let person2 = {
      name: "여름2",
      printThis: printThis,
    };
    person2.printThis(); // {name: '여름2', printThis: ƒ}
    
    let person3 = {
      name: "여름3",
      printThis: printThis,
    };
    person3.printThis(); // {name: '여름3', printThis: ƒ}

     

    🔻예외 경우

    let person = {
      name: "peazh",
      age: 20,
      printThis: function () {
        console.log(this);
      },
    };
    
    let printThis = person.printThis;
    printThis(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    • 객체의 메서드를 변수에 할당한 후 호출하면, 메서드와 객쳉의 연결이 끊어져 this는 전역 객체를 가리키게 됨
    • 그래서 메서드 호출이 아닌 일반 함수 호출처럼 동작함

     

    04) 화살표 함수

    • 자신이 선언된 외부 스코프에서 this를 그대로 상속받음
    • 정적으로 바인딩(선언된 시점의 스코프에 따라 결정)되며, 화살표 함수의 내부 this는 변하지 않음

     

    🔻일반 함수를 사용

    let person = {
      name: "peazh",
      age: 20,
      hello: function () {
        setTimeout(function () {
          console.log(this)
        }, 1000);
      },
    };
    person.hello(); //Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    • setTimeout 같은 비동기 함수의 콜백으로 전달된 함수는 특별히 다른 바인딩이 없는 한 전역 스코프에서 실행
    • 콜백 함수는 객체의 메서드로 호출된 것이 아니라 단독으로 호출된 것으로, this가 전역 객체를 참조함

     

    🔻일반 함수를 화살표 함수로 변경

    let person = {
      name: "peazh",
      age: 20,
      hello: function () {
        setTimeout(() => {
          console.log(this);
        }, 1000);
      },
    };
    person.hello(); // {name: 'peazh', age: 20, hello: ƒ}
    • this는 화살표 함수를 포함하고 있는 외부 스코프 person 객체를 가리킴

     

    🔻화살표 함수를 사용하면 안되는 경우

    let person = {
      name: "peazh",
      age: 20,
      hello: () => {
        console.log(this);
      },
    };
    person.hello(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    • hello의 외부 스코프는 전역 스코프이기 때문에, 전역 스코프의 this인 window 객체를 반환
    • 이와 같은 경우에는 화살표 함수보다는 일반 함수를 사용해야 함

     

    05) 이벤트 핸들러

     

    🔻일반 함수

    let btn = document.querySelector("button");
    btn.addEventListener("click", function () {
      console.log(this); // <button id="btn">버튼</button>
      console.log(this === btn); // true
    });
    • 일반 함수에서 this는 호출되는 DOM 요소(이벤트가 발생한 대상)를 가리킴

     

    🔻화살표 함수

    let btn = document.querySelector("button");
    btn.addEventListener("click", () => {
      console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    });
    • 이벤트 핸들러로 전달될 함수의 this는 호출 시점에 결정되는데, 화살표 함수는 그 자체로는 this를 바인딩하지 않기 때문에 전역 객체를 참조함

     

    06) 엄격 모드

    • 엄격 모드(Strict Mode)에서는 기본값이 전역 객체가 아닌 undefined로 설정되어, 더욱 엄격하게 검사함

     

    🔻non strict mode

    function printThis() {
      console.log(this);
    }
    printThis(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}

     

    🔻strict mode

    'use strict'
    function printThis() {
      console.log(this);
    }
    printThis(); // undefined

     

    07) bind 메서드 사용

    • bind를 사용하여 this의 값을 명시적으로 설정할 수 있음
    • 원하는 함수에 바인드 메서드를 호출한 뒤 객체를 파라미터로 전달해주면 됨
    function printThis() {
      console.log(this);
    }
    // this를 마음대로 변경하기
    let person = {
      name: "한여름",
    };
    
    let printThis1 = printThis.bind(person);
    printThis1(); // {name: '한여름'}

     

    🔻주의사항

    let person1 = {
      name: "한여름",
    };
    let person2 = {
      name: "최여름",
    };
    
    let printThis1 = printThis.bind(person1);
    let printThis2 = printThis1.bind(person2);
    printThis2(); // {name: '한여름'}
    • bind는 한 번 바인딩된 함수의 this 값을 다시 바인딩할 수 없음
    • 그래서 printThis1을 person1에 바인딩한 후 다시 바인딩을 시도해도, '최여름'이 아닌 '한여름'이 출력됨

     

    🔻bind 메서드 사용 전

    let person = {
      name: "peazh",
      age: 20,
      hello: function () {
        setTimeout(function () {
          console.log(this.name);
          console.log(this.age); // undefined
        }, 1000);
      },
    };
    person.hello();
    • setTimeout에서의 콜백 함수가 일반 함수로 호출되기 때문에 this는 전역 객체를 가리킴
    • 그래서 this.name, age는 undefined가 출력됨

     

    🔻bind 메서드 사용 후

    let person = {
      name: "peazh",
      age: 20,
      hello: function () {
        setTimeout((function () {
          console.log(this.name); // peazh
          console.log(this.age); // 20
        }).bind(this), 1000);
      },
    };
    person.hello();
    • bind를 사용하여 this를 명시적으로 person 객체로 고정

     

    반응형

    댓글