[영상후기] [10분 테코톡] 하리의 this

박철현·2023년 5월 3일
0

영상후기

목록 보기
119/160

movie

this란?

This

  • this : (객체지향 언어) 클래스로 생성한 인스턴스 객체
    • 자바스크립트에서는 클래스가 아니여도 사용 가능
    • 객체를 가르킨다 할수도 있음

객체

  • 객체 : Property(상태) + Method(동작)
    • 메서드가 프로퍼티 참조하려면, 자신이 속한 객체를 가르키는 식별자를 참조할 수 있어야 함
    • ex) this.name

자바스크립트의 this

  • 함수 호출 시 결정
    • 함수 호출 시 실행 컨텍스트 생성 -> 실행컨텍스트가 생성될 때 this가 결정 -> 따라서 함수 호출 시 결정된다 고 할 수 있음
    function printThis() {
        console.log(this);
      }
     printThis();

this 바인딩

  • this가 가르칠 객체를 연결하는 것
    • 함수 호출 방식에 의해 독립적으로 결정

함수 호출 방식

  • 일반 함수 호출 (기본 바인딩)
  • 메서드 호출 (암시적 바인딩)
  • 생성자 함수 호출 (new 바인딩)
  • Function.prototype.apply/call/bind 메서드에 의한 간접 호출(명시적 바인딩)

일반 함수 호출(기본 바인딩)

  • 일반 함수 호출 시 기본적 this에는 전역 객체 바인딩
    • Node의 경우 상황에 따라 exporse 빈 객체가 바인딩 되기도 함
function printThis() {
  console.log(this); // Browser : window / Node : global
}
printThis();
  • 엄격 모드 에서는 바인딩이 다르게 됨(전역객체가 아닌 undefined 객체 바인딩)
function printThis() {
  'use strict';
  console.log(this); // undefined
}

printThis();

기본 바인딩 예시

// 왼 - 함수 안에서 또 다른 함수 선언
const obj = {
  foo() {
    function boo() {
      console.log(this);
    }
    boo();
  },
};

// 오 - 함수 안에서 setTimeOut의 콜백함수 선언하여 사용
const obj = {
  foo() {
   setTimeout(function () {
     console.log(this);
   }, 0);
  },
};
  • (왼) 중첩 함수 : 함수 안에서 또 다른 함수를 선언 하여 사용
  • (오) 함수 안에서 setTimeout의 콜백 함수를 선언하여 사용
  • 중첩, 콜백 함수 선언을 일반함수로 선언하는 공통점이 있음
    • this가 전역 객체로 바인딩

문제점

  • 자신이 속한 객체의 메서드에 접근 하려고 했는데, 전역 객체로 접근을 하게 되어 원하는 기능을 수행하지 못할 수 있음
해결책) this로 사용하고자 하는 객체를 변수에 할당하여 사용
	const me = {
      name : 'Halee',
      printName() {
        // 암시적 바인딩에 의해 me 객체가 됨
        const self = this;
        setTimeout(function() {
          console.log(self.name);
          }, 0);
       },
    };

     me.printName(); // Halee 
  • 암시적 바인딩으로 me 객체 가리키게 가능
    - apply, call, bind 메서드를 사용하여 명시적 바인딩도 가능
    • 화살표 함수를 사용하여 this를 통일하는 방법도 존재

암시적 바인딩(메서드 호출) & 예시

  • 함수를 객체의 메서드로 호출할 경우 this는 메서드를 호출할 때 메서드 이름 앞에 적힌 객체로 바인딩
const outer = {
  inner : {
    printThis() {
      console.log(this);
    },
  },
};

// this는 inner로 바인딩 됨
outer.inner.printThis();

new 바인딩(생성자 함수 호출)

  • 생성자 함수 : 객체, 인스턴스를 생성하는 함수
  • 생성자 함수 내부 this에는 함수를 사용하여 생성할 인스턴스 바인딩
function Someone(name) {
  this.name = name;
}
// 내부 this에는 me 가 바인딩
const me = new Someone('Halee');

명시적 바인딩(apply, call, bind 메서드에 의한 간접 호출)

  • apply, call, bind 메서드는 Function.prototype의 메서드로 모든 함수가 상속받아 사용할 수 있음
    • Function.prototype.apply(thisArg, argsArray) : this로 사용할 객체, 함수에게 전달할 인수리스트의 배열 또는 유사객체를 전달받음
    • Function.prototype.call(thisArg, arg1, arg2,...) : this로 사용할 객체, 함수에게 전달할 인수 리스트를 하나하나 받음
      • 두 메서드는 인수 전달방법만 다르며, this로 사용할 객체를 전달하면서 알아서 함수를 호출해줌
    • Function.prototype.bind(thisArg, arg1, arg2, ...): this로 사용할 객체, 함수에게 전달할 인수 리스트를 하나하나 받음
    • 함수를 호출해주지 않음, thisArg로 바인딩된 함수 반환
    • 호출해주는 작업 필요

바인딩 규칙 항상 중첩되지 않는가?

  • 코드에서 규칙이 중첩되지 경우 존재함, 규칙간 적용 가능한 우선순위 존재

암시적 바인딩 vs 명시적 바인딩

  • 명시적 바인딩 > 암시적 바인딩
const someone = {
  name : 'Halee',
  printName() {
    console.log(this.name);
  },
};

// 1. printName을 someone의 메서드로 호출하면서 암시적 바인딩
// 2. bind 메서드를 사용해 this의 name을 Zzanggu로 명시적 바인딩
// 이 경우 명시적 바인딩이 된 객체 값인 짱구가 출력됨
someone.printName.bind( { name: 'Zzanggu' } )();

명시적 vs new 바인딩

  • new 바인딩 > 명시적 바인딩
function setName(name) {
  this.name = name;
}
let someone = {
  name: 'Halee',
};
// 1. 명시적 바인딩 호출
const setNameBindSomeone = setName.bind(someone);

// 2. new 바인딩 호출
someone = new setNameBindSomeone('Zzanggu');
// 3. 짱구 출력
console.log(someone.name);

this 바인딩 규칙 우선순위

  • new > 명시적 > 암시적 > 기본바인딩

화살표 함수에서의 this

  • 일반함수 내부에서 this가 전역객체를 바라보는 문제를 해결하고자 등장
const arrowFn = () => {
  console.log('나는야 화살표 함수');
}
  • 실행컨텍스트를 생성할 때 this 바인딩 과정을 하지 않음 -> 화살표 함수 내 this 존재하지 않음
    • this 호출 시 상위 스코프의 this에 접근
    • Lexical this라 함
  • 화살표 함수 내부에서 사용할 this는 call, bind, apply 메서드를 사용하여 명시적 바인딩을 해주더라도 화살표 함수 내부에서 사용할 this는 교체할 수 없음
    • 화살표 함수 자체에 this 바인딩이 존재하지 않기 때문

화살표 함수 예시

const someone = {
  name : 'Halee',
  printName : () => {
    console.log(this.name);
  },
};
// 암시적 바인딩에 의해 this 가 someone일 것 같음 -> 실제로는 전역객체 바인딩
// scope chain에 의해 나온 가장 가까운 객체가 전역 객체
// 하지만 실제 결과는 브라우저 에서는 빈 문자열 / 노드에서는 undefined 출력
// window 객체의 name값이 기본값으로 빈 문자열로 설정
someone.printName();
  • 가장 가까운 상위 스코프의 this가 전역객체인 경우 축약 메서드로 사용하는 것이 좋음
const someone = {
  name : 'Halee',
  printName() {
    console.log(this.name);
  },
};
// 암시적 바인딩에 의해 this 가 someone으로 동작
someone.printName();

클래스에서의 this

class SomeClass {
  
}
  • 엄격모드일 때 전역 객체가 아닌 undefined
  • 클래스 내부는 암묵적으로 엄격모드 적용
    • 일반적으로 내부에서 this 호출 시 클래스를 통해 생성한 인스턴스객체로 바인딩
    • 메소드 내부의 중첩함수나 콜백함수 등을 일반 함수로 선언, 호출 시 undefined가 됨
      • this를 변수에 할당
      • 명시적 바인딩, 화살표 함수 등 사용

정리

바인딩 규칙

  • 일반 함수 호출(기본 바인딩) : 전역 객체 or undefined
  • 메서드 호출(암시적 바인딩) : 호출 객체
  • 생성자 함수 호출(new 바인딩) : 인스턴스 객체
  • apply, call, bind에 의한 간접 호출 (명시적 바인딩) : 첫 번째 인자 객체

바인딩 우선순위

new > 명시적 > 암시적 > 기본

화살표 함수

  • this 바인딩 x
  • 상위 스코프의 this에 접근

Class

  • 내부 엄격모드 적용
  • 일반적으로 this : 인스턴스 객체
  • 중첩함수나 콜백함수 로 일반 함수 선언, 호출 시 this : undefined
profile
비슷한 어려움을 겪는 누군가에게 도움이 되길

0개의 댓글

관련 채용 정보