fffo

this 본문

Programming/Javascript

this

gggs 2021. 10. 6. 18:44

this

this 키워드

  • 메서드가 자신이 속한 객체의 프로퍼티를 참조하려면 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야함
  • 그러나 생성자 함수 내부의 메서드는 자신이 속할 객체를 가리키는 식별자를 알 수 없음
  • this는 자신이 속한 객체 또는 속할 인스턴스를 가리키는 자기 참조 변수
  • this는 js엔진에 의해 암묵적으로 생성되고 함수 호출 방식에 의해 동적으로 바인딩됨

함수 호출 방식과 this 바인딩

일반 함수 호출

  • this에 전역 객체가 바인딩 됨
  • 객체를 생성하지 않는 일반 함수에서는 this가 의미 없고 사용 시 혼란만 가중 되므로 strict mode 적용시 this에는 undefined가 바인딩 됨
  • 메서드 내에 정의한 중첩 함수, 일반 함수로 호출된 콜백 함수도 this에 전역 객체가 바인딩 됨
var value = "global's val";

const obj = {
  value: "object's val",
  foo() {
    console.log(this.value); // object's val
    function bar() {
      console.log(this.value); // global's val
    }
    bar();
    setTimeout(function() {
      console.log(this.value); // global's val
    },0);
  }
};
obj.foo();
  • 이러한 this 불일치는 헬퍼 함수로 동작하기 어렵게 만들기 때문에 일치 시키기 위한 방법이 있음
    • Function.prototype.apply/call/bind 메서드
    • 화살표 함수

메서드 호출

  • 메서드를 호출한 객체, 즉 메서드를 호출할 때 메서드 이름 앞의 마침표 연산자 앞에 기술한 객체가 this에 바인딩 됨
  • 메서드를 소유한 객체가 아닌 메서드를 호출한 객체에 바인딩 된다는 것에 유의

생성자 함수 호출

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

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

  • 공통적으로 첫번째 인자로 this에 바인딩할 객체를 넘김
  • apply와 call은 함수 호출까지 하지만 bind는 따로 함수를 호출해야함
  • apply는 함수에게 전달할 인수 배열 혹은 유사배열객체를 둘 째 인자로 받고 call은 인자로 this에 둘 째 인자 이후부터 함수에게 전달할 인수들을 받음
function test() {
  console.log(arguments);
  return this;
}

const thisArg = { a: 1};

console.log(test.apply(thisArg,[1,2,3]));
console.log(test.call(thisArg, 1, 2, 3));
console.log(test.bind(thisArg)(1, 2, 3));

/*
[Arguments] { '0': 1, '1': 2, '2': 3 }
{ a: 1 }

모두 출력 값 동일
*/

this 바인딩 실습

const person = {
  name: 'dlwlrma',
  test(callback) {
    setTimeout(callback, 0);
  }
};

const callbackFunc = function () {
  console.log(`Hi. my name is ${this.name}`);
};

// 일반 함수로 호출된 함수의 this는 전역객체
person.test(callbackFunc); 

// test의 this에는 원래 person이 바인딩 되어 있다
person.test.call(person, callbackFunc);

// setTimeout에 call로 전달된 this는 setTimeout 함수 몸체에 전달된다
person.test = function (callback) {
  setTimeout.call(this, callback, 0);
}
person.test(callbackFunc);

// 일반 함수로 호출되는 콜백함수에 직접 this를 바인딩해줘야 한다
person.test = function (callback) {
  setTimeout(callback.bind(this),0);
}
person.test(callbackFunc);

 

'Programming > Javascript' 카테고리의 다른 글

클로저  (0) 2021.10.11
실행 컨텍스트  (0) 2021.10.07
빌트인 객체  (0) 2021.10.05
strict mode  (0) 2021.10.04
프로토타입  (0) 2021.10.03
Comments