https://media.vlpt.us/images/modolee/post/f7f22bb8-a50e-4a28-b8bc-a74b05429116/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-09-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.46.20.png

상황에 따라 달라지는 this


  • this는 함수를 호출할 때 결정된다.

전역 공간에서의 this

  • 전역 공간에서의 this는 전역 객체를 가리킴
  • 브라우저 - window, Node - global
var a = 1;
console.log(a); // 1
console.log(window.a); // 1
console.log(this.a); // 1
  • 자바스크립트의 모든 변수는 실은 특정 객체의 프로퍼티로서 동작한다.
  • 전역변수 선언과 전역객체의 프로퍼티 할당의 차이는 삭제 명령에 있다. 전역 변수 선언은 delete 로 삭제가 되지 않지만, 전역객체의 프로퍼티 할당은 delete로 삭제가 된다.
  • var로 선언한 전역변수와 전역객체의 프로퍼티는 호이스팅 여부 및 configurable(변경 및 삭제) 여부에서 차이를 보인다.

메서드로서 호출할 때 그 메서드 내부에서의 this

함수 vs 메서드

  • 함수는 그 자체로 독립적인 기능을 수행
  • 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행
var func = function (x) {
  console.log(this, x);
};
func(1); // Window { ... } 1

var obj = {
  method: func
};
obj.method(2); // {method: f} 2
  • 함수 앞에 . 또는 obj['method'] 로 호출했다면 이는 메서드 로 호출한 것임
  • 어떤 함수를 메서드로서 호출하는 경우 호출 주체는 바로 함수명 앞의 객체 이다.

함수로서 호출될 때 그 함수 내부에서의 this

  • 변수에 this를 담아서 내리는 방법도 있다.
  • 화살표 함수를 사용하면 this를 바인딩 하지 않는 함수를 만들 수 있다.

콜백 함수 호출 시 그 함수 내부에서의 this

  • 콜백 함수의 제어권을 가지는 함수(메서드)가 콜백 함수에서의 this를 무엇으로 할지 결정

생성자 함수 내부에서의 this

  • 생성자는 구체적인 인스턴스를 만들기 위한 틀
  • 생성자 함수를 호출하면 생성자의 prototype 프로퍼티를 참조하는 proto 라는 프로퍼티가 있는 객체를 만들고, 미리 준비된 공통 속성 및 개성을 해당 객체(this)에 부여

명시적으로 this를 바인딩하는 방법


Call 메서드

Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])
  • call 메서드는 메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령
  • 이때 call메서드의 첫번째 인자를 this로 바인딩 하고 이후의 인자들을 호출할 함수의 매개변수로 함
  • call 메서드를 활용하면 임의의 객체를 this로 지정할 수 있음
var obj = {
  a: 1,
  method: function (x, y) {
    console.log(this.a, x, y);
  }
};

obj.method(2, 3); // 1 2 3
obj.method.call({ a: 4 }, 5, 6); // 4 5 6

apply 메서드

Function.prototype.apply(thisArg[, argsArray])
  • apply 메서드는 call 메서드와 같지만 두번째 인자를 배열로 받아 이를 호출할 함수의 매개변수로 지정

call / apply 메서드의 활용

유사배열객체에 배열 메서드를 적용

var obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};
Array.prototype.push.call(obj, 'd');
console.log(obj); // {0: "a", 1: "b", 2: "c", 3: "d", length: 4}

var arr = Array.prototype.slice.call(obj);
console.log(arr); // ["a", "b", "c", "d"]

생성자 내부에서 다른 생성자 호출

function Person(name, gender) {
  this.name = name;
  this.gender = gender;
}

function Student(name, gender, school) {
  Person.call(this, name, gender);
  this.school = school;
}

function Employee(name, gender, company) {
  Person.apply(this, [name, gender]);
  this.company = company;
}
  • call과 apply 메서드는 명시적으로 별도의 this를 바인딩하면서 함수 또는 메서드를 실행하는 훌륭한 방법이지만 오히려 이로 인해 this를 예측하기 어렵게 만들어 코드 해석을 방해한다는 단점이 있다.

bind 메서드

Function.prototype.bind(thisArg[, arg1[,arg2[, ...]]])
  • bind는 call과 비슷하지만 즉시 호출하지 않고 념겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드
  • bind 메서드를 적용하여 새로 만든 함수는 name 프로퍼티에 bound 접두어가 붙는다
var func = function (a, b, c, d) {
  console.log(this, a, b, c, d);
}

var bindFunc = func.bind({ x: 1 }, 4, 5);
console.log(func.name); // --- func
console.log(bindFunc.name); // bound func

상위 컨텍스트의 this를 내부함수나 콜백 함수에 전달하기

  • 앞에서 변수를 활용한 우회법을 사용했지만 call, apply, bind를 활용하면 더 깔끔하다.
var objWithCall = {
  outer: function () {
    console.log(this); // - objWithCall
    var innerFunc = function () {
      console.log(this); // objWithCall
    };
    innerFunc.call(this);
  }
};
objWithCall.outer();

var objWithBind = {
  outer: function () {
    console.log(this); // - objWithBind
    var innerFunc = function () {
      console.log(this); // objWithBind
    }.bind(this);
    innerFunc();
  }
};
objWithBind.outer();

화살표 함수의 예외 상황

  • ES6에 새롭게 도입된 화살표 함수는 실행 컨텍스트 생성 시 this를 바인딩하는 과정이 제외되었다. 스코프 체인상 가장 가까운 this에 접근하게 된다.

별도의 인자로 this를 받는 경우 (콜백 함수 내에서의 this)

var report = {
  sum: 0,
  count: 0,
  add: function () {
    var args = Array.prototype.slice.call(arguments);
    args.forEach(function (entry) {
      this.sum += entry;
      ++this.count;
    }, this); // 이처럼 마지막에 this를 넘겨준다.
  },
  average: function () {
    return this.sum / this.count;
  }
};
report.add(60, 85, 95);
console.log(report.sum, report.count, report.average()); // 240 3 80
  • 콜백 함수를 인자로 받는 메서드 중 일부는 추가로 this로 지정 할 객체(thisArg)를 인자로 지정 할 수 있는 경우가 있음
  • thisArg를 지정하면 콜백 함수 내부의 this 값을 원하는 대로 변경 가능
  • 여러 내부 요소에 대해 같은 동작을 반복 수행하는 배열 메서드에 많이 포진
    • Arrary의 forEach, map, filter, some, every, find, findIndex, flatMap, from
    • Set, Map (ES6에 추가) 의 forEach
profile
프론트엔드 개발자

0개의 댓글

관련 채용 정보

Powered by GraphCDN, the GraphQL CDN