ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 this
    JavaScript 2021. 12. 16. 16:16
    • 자신이 속한 객체의 프로퍼티를 참조하려면 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야함
    • 객체의 프로퍼티 : 객체 고유의 상태 데이터
    • 객체의 메서드 : 객체 상태 데이터를 참조/조작하는 동작
    const circle = {
      radius: 5, // 프로퍼티
      getDiameter() { // 메서드
        return 2 * circle.radius; 
        // 이 메서드가 자신이 속한 객체의 프로퍼티나 다른 메서드를 참조하려면
        // 자신이 속한 객체인 circle을 참조할 수 있어야 한다.
      }
    };
    
    console.log(circle.getDiameter()); // 10
    • 위와 같이 가능하지만(circle.radius를 참조) 자기 자신을 재귀적으로 참조하는 것은 좋지 않음, 
    • 위와 같은 방법은 직관적이고 편하지만, 동일한 프로퍼티를 갖는 객체를 여러개 생성해야 하는 경우 생성자 함수를 통해 객체를 생성하는 것이 더 좋다(객체 지향 프로그래밍)

    this: 자신이 속한 객체, 자신이 생성한 인스턴스를 가르키는 자기 참조 변수

    • this 는 자바스크립트 엔진에 의해 암묵적으로 생성되고, this의 값은 함수 호출 방식에 의해 동적으로 결정
    // 호출 방식에 따른 this의 값
    // 객체
    const circle = {
      radius: 5,
      getDiameter() {
        return 2 * this.radius; // this는 메서드를 호출한 객체를 가리킨다.
      }
    };
    
    console.log(circle.getDiameter()); // 10 circle 객체가 호출함.
    
    // 생성자 함수
    function Circle(radius) {
      this.radius = radius; // this는 생성자 함수가 생성할 인스턴스를 가리킨다.
    }
    
    Circle.prototype.getDiameter = function () {
      // this는 생성자 함수가 생성할 인스턴스를 가리킨다.
      return 2 * this.radius;
    };
    
    // 인스턴스 생성
    const circle = new Circle(5);
    console.log(circle.getDiameter()); // 10 circle 인스턴스를 가르침
    • 호출 방식에 따른 this의 값
      • 전역 - window
      • 일반함수-window or undefined(strict mode)
      • 객체 - 호출한 객체
      • 생성자 함수 - 인스턴스

     

    // this는 어디서든지 참조 가능하다.
    // 1. 전역에서 this는 전역 객체 window를 가리킨다.
    console.log(this); // window
    
    // 2. 일반 함수 내부에서 this는 전역 객체 window를 가리킨다.
    function square(number) {
      console.log(this); // window
      return number * number;
    }
    square(2);
    
    // 3. 메서드 내부에서 this는 메서드를 호출한 객체를 가리킨다.
    const person = {
      name: 'Lee',
      getName() {
        console.log(this); // person 객체이므로, {name: "Lee", getName: ƒ}
        return this.name;
      }
    };
    console.log(person.getName()); // Lee
    
    // 4. 생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
    function Person(name) {
      this.name = name;
      console.log(this); // me 라는 인스턴스 {name: "Lee"}
    }
    
    const me = new Person('Lee');
    • 중첩 함수의 경우 바인딩을 해주시 않으면 window 에서 value를 찾음
    • 부모 함수에서 const that = this 를 통해 바인딩 해줌
    var value = 1;
    
    const obj = {
      value: 100,
      foo() {
        console.log("foo's this: ", this);  // {value: 100, foo: ƒ} // obj 객체 값
    
        function bar() {  // 메서드 내에서 정의한 중첩 함수
          console.log("bar's this: ", this); // window
          console.log("bar's this.value: ", this.value); // 1 // window.value 가 됨
        }
        // 이슈: 메서드 내에서 정의한 중첩 함수도 일반 함수로 호출되면 **중첩 함수 내부의 this에는 전역 객체가 바인딩**된다.
        bar();
      }
    };
    
    obj.foo();
    
    var value1 = 1;
    
    // that - this - 컨밴션
    const obj1 = {
        value1: 100,
        foo() {
            console.log("foo's this: ", this);  // {value: 100, foo: ƒ} // obj 객체 값
            const that = this; // 해결 방법
            function bar() {  // 메서드 내에서 정의한 중첩 함수
                console.log("bar's this: ", that); // window
                console.log("bar's this.value: ", that.value1); // 100
            }
            // 이슈: 메서드 내에서 정의한 중첩 함수도 일반 함수로 호출되면 **중첩 함수 내부의 this에는 전역 객체가 바인딩**된다.
            bar();
        }
    };
    
    obj1.foo();
    
    var value = 1;
    
    const obj = {
      value: 100,
      foo() {
        const that = this;   // this 바인딩(obj)을 변수 that에 할당한다. 
        setTimeout(function () {  
          console.log(that.value); // 100 콜백 함수 내부에서 this 대신 that을 참조한다.
        }, 100);
      }
    };
    
    obj.foo();
    
    var value = 1;
    
    const obj = {
      value: 100,
      foo() {
        setTimeout(function () {
          console.log(this.value); // 100
        }.bind(this), 100); // 콜백 함수에 명시적으로 this를 바인딩한다.
      }
    };
    
    obj.foo();
    var value = 1;
    
    const obj = {
      value: 100,
      foo() {
        // 화살표 함수 내부의 this는 상위 스코프의 this를 가리킨다.
        setTimeout(() => console.log(this.value), 100); // 100
      }
    };
    
    obj.foo();
    • 객체의 메서드가 변수에 할당되면 그 메서드 안의 this 는 객체의 메서드가 아닌 일반 함수가 되기에 window에서 해당 값을 찾는다.
    onst anotherPerson = {
      name: 'Kim'
    };
    anotherPerson.getName = person.getName;
    console.log(anotherPerson.getName()); // Kim // this => object
    
    const getName = person.getName; // getName 메서드를 변수에 할당
    
    console.log(getName()); // '' // getName 메서드를 일반 함수로 호출 
    // 호출 시 객체가 호출 하는 것이 아닌 변수에 할당된 일반 함수가 호출되며,
    // 일반 함수로 호출된 getName 함수 내부의 this.name은 브라우저 환경에서 window.name과 같다.
    // 브라우저 환경에서 window.name은 브라우저 창의 이름을 나타내는 빌트인 프로퍼티이며 기본값은 ''이다.
    // Node.js 환경에서 this.name은 undefined​
    • 생성자 함수의 this / 생성자함수를 new 없이 생성시
    function Circle(radius) {
      this.radius = radius;
      this.getDiameter = function () {
        return 2 * this.radius;
      };
    }
    
    const circle1 = new Circle(5);
    const circle2 = new Circle(10);
    
    console.log(circle1.getDiameter()); // 10
    console.log(circle2.getDiameter()); // 20
    
    // new 연산자와 함께 호출하지 않으면 생성자 함수로 동작하지 않는다. 
    // 일반적인 함수의 호출이다.
    const circle3 = Circle(15);
    
    // 일반 함수로 호출된 Circle에는 반환문이 없으므로 암묵적으로 undefined를 반환
    console.log(circle3); // undefined
    
    // 일반 함수로 호출된 Circle 내부의 this는 전역 객체를 가리킨다.
    // this.radius = radius  => window.radius = 15
    console.log(radius); // 15
    • Apply, call, bind 적용
      • Apply, call 함수를 바로 실행함
      • bind 는 새로운 함수를 반환하기에 명시적으로 호출해야함
    function getThisBinding() {
      return this;
    }
    
    const thisArg = { a: 1 }; / / this로 사용할 객체
    console.log(getThisBinding()); // window // 일반함수의 this
    
    // getThisBinding 함수를 호출하면서 인수로 전달한 객체를 getThisBinding 함수의 this에 바인딩한다.
    console.log(getThisBinding.apply(thisArg)); // {a: 1} // this 값에 thisArg가 할당됨 - 바인딩
    console.log(getThisBinding.call(thisArg)); // {a: 1} // this 값에 thisArg가 할당됨 - 바인딩
    
    // arguments 인수 전달도 가능
    function getThisBinding() {
      console.log(arguments);
      return this;
    }
    const thisArg = { a: 1 };
    console.log(getThisBinding.apply(thisArg, [1, 2, 3])); // apply 는 배열로
    // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
    // {a: 1}
    
    console.log(getThisBinding.call(thisArg, 1, 2, 3)); // call 는 인수 하나씩
    // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
    // {a: 1}
    
    
    function getThisBinding() {
      return this;
    }
    
    const thisArg = { a: 1 };
    
    // bind 메서드는 첫 번째 인수로 전달한 thisArg로 this 바인딩이 교체된
    // getThisBinding 함수를 새롭게 생성해 반환한다.
    console.log(getThisBinding.bind(thisArg)); // getThisBinding
    // bind 메서드는 함수를 호출하지는 않으므로 명시적으로 호출해야 한다.
    console.log(getThisBinding.bind(thisArg)()); // {a: 1}
    • bind 활용
    const person = {
      name: 'Lee',
      foo(callback) {
        setTimeout(callback, 100);
      }
    };
    
    person.foo(function () {
      console.log(`Hi! my name is ${this.name}.`); // ② Hi! my name is .
      // 일반 함수로 호출된 콜백 함수 내부의 this 는 window 
      // 브라우저 환경에서 window.name 으로 이 값은 브라우저 창의 이름을 나타내는 빌트인 프로퍼티이며 기본값은 ''이다.
      // Node.js 환경에서 this.name은 undefined
    });
    
    // person 객체의 this를 callback 내부의 this 바인딩을
    const person = {
      name: 'Lee',
      foo(callback) {
        setTimeout(callback.bind(this), 100);
      }
    };
    
    person.foo(function () {
      console.log(`Hi! my name is ${this.name}.`); // Hi! my name is Lee.
    });

    'JavaScript' 카테고리의 다른 글

    NodeJS - Express, file structure  (0) 2022.02.19
    Docker - Express(TS) - Config(Prod,dev,test)  (0) 2022.01.30
    빌트인 객체, 래퍼 객체  (0) 2021.12.17
    변수(var, let, const) + feat.메모리  (0) 2021.12.16
    JS - GOOD/BAD CODE  (0) 2021.07.18
Designed by Tistory.