22. this




this 키워드

  • 객체에서 동작을 나타내는 메서드는, 프로퍼티를 참조하고 변경할 수 있어야 한다.
    • 메서드가 자신이 속한 객체의 프로퍼티를 참조하려면, 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다.
const circle = {
  r: 5,
  getDiameter() {
    //객체 리터럴로 생성된 객체는 재귀적으로 참조 가능
		// 사용 지양!
    return 2 * circle.r;
  },
};
  • 생성자 함수는 자신이 생성할 인스턴스를 참조할 수 있어야해.
    • 생성자 함수를 정의하는 시점에는 아직 인스턴스 없어. > 인스턴스 가리키는 식별자 몰라
    • 자신이 생성할 인스턴스를 가리킬 식별자 필요 > this
  • this : 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수.
    • this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다
  • this는 js 엔진에 의해 암묵적으로 생성, 어디서든지 참조 가능
  • 함수 호출 시, arguments 객체와 this가 암묵적으로 함수 내부에 전달
    • this를 지역 변수처럼 사용 가능
    • this 가 가리키는 값, 즉 this 바인딩은 함수 호출 방식에 의해 동적으로 결정
    • this 바인딩 : 식별자와 값을 연결하는 과정 > this 와 this가 가리킬 객체를 바인딩하는 것
  • js의 this는 함수가 호출되는 방식에 따라 this 바인딩이 동적으로 결정된다.

2. 함수 호출 방식과 this 바인딩

  • this 바인딩은 함수 호출 방식, 즉 함수가 어떻게 호출되었는지에 따라 동적으로 결정
  • 렉시컬 스코프와 this 바인딩은 결정 시기가 다르다
    • 함수의 상위 스코프를 결정하는 방식인 렉시컬 스코프는 함수 정의가 평가되어 함수 객체가 생성되는 시점에 상위 스코프를 결정
    • this 바인딩은 함수 호출 시점에 결정
  • 함수 호출 방식
    • 일반 함수 호출
    • 메서드 호출
    • 생성자 함수 호출
    • Function.prototype.apply/call/bind 메서드에 의한 간접 호출

일반 함수 호출

  • this에는 전역 객체가 바인딩
  • 중첩 함수도 일반 함수로 호출하면 this에는 전역 객체 바인딩
  • 일반함수는 객체를 생성하지 않아서 의미가 없다 > strict mode에는 undefined가 바인딩
    • 콜백함수도 this 에 전역객체 바인딩
  • 일반 함수로 호출된 모든 함수(중첩 함수, 콜백 함수 포함) 내부의 this에는 전역 객체가 바인딩
    • 중첩, 콜백이 이렇게 작동하는건 헬퍼 함수로서 역할 x
    • 해결법 : that, Function.prototype.apply(call,bind), arrowFunction

메서드 호출

  • 메서드 내부의 this : 메서드를 호출한 객체, 마침표 연산자 앞에 기술한 객체가 바인딩 된다.
    • 주의 : 메서드를 소유한 객체가 아닌 매서드를 호출한 객체에 바인딩
  • 매서드는 객체에 프로퍼티로 함수가 존재하는 것 > 함수 참조값만 가지고 있고, 실제 함수는 독립적인 또다른 객체다.
    • 객체의 메서드를 다른 객체의 메서드로 할당 가능, 일반 변수에 할당해서 일반 변수로 호출 가능
    • 메서드 내부의 this는 프로퍼티로 메서드를 가리키고 있는 객체와는 관계없이 메서드를 호출한 객체에 바인딩 된다.
  • 프로토타입 메서드 내부에서 사용된 this도 일반 메서드와 같이 해당 메서드를 호출한 객체에 바인딩된다.

생성자 함수 호출

  • 생성자 함수가 미래에 생성할 인스턴스가 바인딩

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

  • Function.prorotype의 메서드라서 모든 함수가 상속 받아 사용 가능
  • this설정하고싶은함수.apply(this로하고싶은값)
  • apply, call의 본질적인 기능은 함수를 호출하는 것.
    • 얘네는 함수를 호출하면서 첫번째 인수로 전달한 특정 객체를 호출한 함수의 this에 바인딩
    • 호출한 함수에 인수를 전달하는 방식만 다를 뿐 동일하게 작동
    • getThisBinding.apply(thisArg, [1,2,3]) : 인수를 배열로 묶어 전달
    • getThisBinding.call(thisArg, 1,2,3) : 쉼표로 구분한 리스트 형식으로 전달
    • 호출할 함수에 인수를 전달하는 방식만 다를 뿐 this로 사용할 객체를 전달하면서 함수를 호출하는 것은 동일
    • apply, call 용도 : argumets 객체와 같은 유사 배열 객체에 배열 메서드를 사용하는 경우
    • arguments는 배열은 아니므로 Array.prototype.slice 같은 거 못쓰는데 얘네 사용하면 쓸 수 있다.
    • Array.prototype.slice.call(arguments)
  • bind는 함수를 호출하지 않고 this로 사용할 객체만 전달한다.
    • 호출하려면 명시적으로 호출해야 한다.
    • getThisBinding.bind(thisArg)()