[모딥다] 22장.this

vanLan·5일 전

모딥다

목록 보기
15/17
post-thumbnail

22장. this

📁 this 키워드

  • this자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수임.

  • this는 JS엔진에 의해 암묵적으로 생성되며, 코드 어디서든 참조가 가능. 함수를 호출하게 되면 arguments 객체this가 암묵적으로 함수 내부에 전달됨.

  • this가 가리키는 값(this 바인딩)은 함수 호출 방식에 의해 동적으로 결정됨.

    // 생성자 함수
    function Circle(radius) {
      // this는 생성자 함수가 생성할 인스턴스를 가리킴
      this.radius = radius;
    }
    
    Circle.prototype.getDiameter = function () {
      // this는 생성자 함수가 생성할 인스턴스를 가리킴
      return 2 * this.radius;
    }
    
    // 인스턴스 생성
    const circle = new Circle(5);
    console.log(circle.getDiameter());  // 10

📁 함수 호출 방식과 this 바인딩

// this 바인딩은 함수 호출 방식에 따라 동적으로 결정됨
const foo = function () {
  console.dir(this);
};

// 1. 일반 함수 호출
foo();  // window

// 2. 메서드 호출
const obj = { foo };
obj.foo();  // obj

// 3. 생성자 함수 호출
new foo();  // foo {}

일반 함수 호출

  • 기본적으로 this에는 전역 객체가 바인딩 됨.

    function foo() {
      console.log("foo's this: ", this);  // window
      
      function bar() {
        console.log("bar's this: ", this);  // window
      }
      bar();
    }
    foo();
  • strict mode가 적용된 일반 함수 내부의 this에는 undefined가 바인딩됨.

    function foo() {
      'use strict';
      
      console.log("foo's this: ", this);  // undefined
      
      function bar() {
        console.log("bar's this: ", this);  // undefined
      }
      bar();
    }
    foo();
  • 일반 함수로 호출된 모든 함수(중첩 함수, 콜백 함수 포함) 내부의 this에는 전역 객체가 바인딩 됨.

    var value = 1;
    
    const obj = {
      value: 100,
      foo() {
        console.log("foo's this: ", this);  // {value: 100, foo: ⨍}
        // 콜백 함수 내부의 this에는 전역 객체가 바인딩 됨
        setTimeout(function () {
          console.log("callback's this: ", this);  // window
          console.log("callback's this.value", this.value);  // 1
        }, 100);
      }
    };
    
    obj.foo();
  • 화살표 함수 내부의 this는 상위 스코프의 this를 가리킴

    var value = 1;
    
    const obj = {
      value: 100,
      foo() {
        // 화살표 함수 내부의 this는 상위 스코프의 this를 가리킴
        setTimeout(() => console.log(this.value), 100);  // 100
      }
    };

메서드 호출

  • 메서드 내부의 this는 메서드를 소유한 객체가 아닌 메서드를 호출한 객체에 바인딩 됨.

    const person = {
      name: 'Lee',
      getName() {
        // 메서드 내부의 this는 메서드를 호출한 객체에 바인딩됨
        return this.name;
      }
    };
    
    // 메서드 getName을 호출한 객체는 person임
    console.log(person.getName());  // Lee
    
    const anotherPerson = {
      name: 'Kim'
    };
    
    // getName 메서드를 anotherPerson 객체의 메서드로 할당
    anotherPerson.getName = person.getName;
    
    // getName 메서드를 호출한 객체는 anotherPerson
    console.log(anotherPerson.getName());  // Kim
    
    // getName 메서드를 변수에 할당
    const getName = person.getName;
    
    // getName 메서드를 일반 함수로 호출
    console.log(getName());  // ''
  • 프로토타입 메서드 내부에서 사용된 this도 일반 메서드와 마찬가지로 해당 메서드를 호출한 객체에 바인딩 됨.

    function Person(name) {
      this.name = name;
    }
    
    Person.prototype.getName = function () {
      return this.name;
    };
    
    const me = new Person('Lee');
    
    // getName 메서드를 호출한 객체는 me
    console.log(me.getName());  // Lee
    
    Person.prototype.name = 'Kim';
    
    // getName 메서드를 호출한 객체는 Person.prototype
    console.log(Person.prototype.getName());  // Kim

생성자 함수 호출

  • 생성자 함수 내부의 this에는 생성자 함수가 생성할 인스턴스가 바인딩됨.

    // 생성자 함수
    function Circle(radius) {
      // 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킴
      this.radius = radius;
      this.getDiameter = function () {
        return 2 * this.radius;
      };
    }
    
    // 반지름 5인 Circle 객체를 생성
    const circle1 = new Circle(5);
    // 반지름 10인 Circle 객체를 생성
    const circle2 = new Circle(10);
    
    console.log(circle1.getDiameter());  // 10
    console.log(circle2.getDiameter());  // 20

Function.prototype.apply/call/bind 메서드에 의한 간접 호출

  • apply, call, bind 메서드는 Function.prototype의 메서드임.(모든 함수가 상속받아 사용 가능)

    const user = { name: "현석" };
    
    function greet(greeting, punctuation) {
      // 원래라면 this는 전역 객체(window)겠지만, call/apply/bind로 user를 가리키게 함
      console.log(`${greeting}, ${this.name}${punctuation}`);
    }
    
    // 1. call 사용 (인수를 쉼표로 나열하여 즉시 실행)
    greet.call(user, "안녕하세요", "!"); 
    // 출력: "안녕하세요, 현석!"
    
    // 2. apply 사용 (인수를 배열로 묶어 전달하며 즉시 실행)
    greet.apply(user, ["반갑습니다", "!!"]); 
    // 출력: "반갑습니다, 현석!!"
    
    // 3. bind 사용 (this가 바인딩된 '새로운 함수'를 반환, 즉시 실행 X)
    const boundGreet = greet.bind(user); 
    
    // 원하는 시점에 호출 (인수는 이때 전달하거나, bind 시 미리 전달 가능)
    boundGreet("어서오세요", "..."); 
    // 출력: "어서오세요, 현석..."
profile
프론트엔드 개발자를 꿈꾸는 이

0개의 댓글