[JS] JS에서 this란?(2)

고정원·2021년 6월 20일
0

1Q/1Day

목록 보기
6/13
post-thumbnail

정재남,『코어자바스크립트』를 읽고 정리한 내용입니다. 이해가 부족한 부분은 책과 동일하게 작성하였습니다.

이전글에서 상황별로 this에 어떤 값이 바인딩되는지 살펴봤지만 이런 규칙을 깨고 this에 명시적으로 별도의 대상을 바인딩 하는 방법도 있다!

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

함수를 실행하는 방법에 function()이외에 call(),apply() 메서드를 사용해서 함수를 즉시 실행할 수 있다. this의 값을 한 문맥에서 다른 문맥으로 넘기려면 .call과 .apply를 사용해야한다.

💡 call()나 apply()의 첫번째 매개변수로 객체를 제공하면 this가 그 객체에 묶인다.

2.1 call메서드

call메서드는 첫 번째 인자를 제외한 나머지 모든 인자들을 호출할 함수의 매개변수로 지정

var obj = {a: 'Custom'};

var a = 'Global';

function whatsThis() {
  return this.a;  
}

whatsThis();          // 'Global'
whatsThis.call(obj);  // 'Custom'
whatsThis.apply(obj); // 'Custom'

2.2 apply메서드

apply메서드는 두 번째 인자를 배열로 받아 그 배열의 요소들을 호출할 함수의 매개변수로 지정

function add(c, d) {
  return this.a + this.b + c + d;
}

var o = {a: 1, b: 3};

// 이어지는 인수들은 함수 호출에 사용할 매개변수
add.call(o, 5, 7); // 16

// 두 번째 매개변수는 배열,
// 각 요소를 함수 호출에 사용
add.apply(o, [10, 20]); // 34

2.3 .call / .apply메서드의 활용

1) 유사배열객체에 배열 메서드를 적용
:객체에는 배열 메서드를 직접 적용할 수는 없다. 그러나 키가 0 또는 양의 정수인 프로퍼티가 존재하고 lenth프로퍼티의 값이 0또는 양의 정수인 객체, 즉 배열의 구조와 유사한 객체의 경우(유사배열객체) call 또는 apply메서드를 이용해 배열 메서드를 빌려 쓸 수 있다.
유사배열객체에는 call/apply 메서드를 이용해 모든
2) 생성자 내부에서 다른 생성자를 호출
:생성자 내부에서 다른 생성자와 공통된 내용이 있을 경우 call 또는 apply메서드를 이용해 다른 생성자를 호출하면 간단하게 반복을 줄일 수 있다.
3) 여러 인수를 묶어 하나의 배열로 전달하고 싶을 때 - apply활용
여러 개의 인수를 받는 메서드에게 하나의 배열로 인수들을 전달하고 싶을 때 apply메서드 사용

var numbers = [10,20,3,16,45];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
console.log(max,min);		//45 3

ES6에서 Spread Operator를 사용하면 apply적용하는 것보다 더 간단하게 구현 가능

var numbers = [10,20,3,16,45];
var max = Math.max.apply(...numbers);
var min = Math.min.apply(...numbers);
console.log(max,min);		//45 3

2.4 bind메서드

bind메서드가 호출되면 새로운 함수를 반환한다. 받게되는 첫 번째 인자의 value로는 this키워드를 설정하고 이어지는 인자들은 바인드된 함수의 인수에 제공된다.

this.x = 9;
var module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX(); // 81 - 함수의 메서드이므로  전역 스코프가 아닌 부모 obj에서 호출됐음

var retrieveX = module.getX;
retrieveX();
// 9 반환 - 함수가 전역 스코프에서 호출됐음 (주의)

// module과 바인딩된 'this'가 있는 새로운 함수 생성
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81

2.5 화살표 함수에서의 this

화살표 함수에서의 this는 자신을 감싼 정적 범위(lexical context)이다. 즉 이 함수 내부에는 this가 아예 없고, 접근하려면 scope체인상 가장 가까운 this에 접근한다.

var obj = {
 i:10,
 b: () => console.log (this.i,this), //undefined, window
 c: function() {
  console.log(this.i, this) //10, obj
  }
} 

정리

크게 아래의 두 가지 상황에서 각 경우에 this가 무엇일지 예측해보는 연습이 필요하다.

1) 명시적 this바인딩이 없는 한 늘 성립

  • 전역공간에서의 this는 전역객체(브라우저-window, Node.js-global)를 참조한다
  • 어떤 함수를 메서드로서 호출한 경우, this는 메서드 호출 주체(메서드명 앞의 객체)를 참조한다.
  • 어떤 함수를 함수로서 호출한 경우 this는 전역객체를 참조한다. 메서드의 내부함수에서도 같다.
  • 콜백함수 내부에서의 this는 해당 콜백 함수의 제어권을 넘겨받은 함수가 정의한 바에 따르며, 정의하지 않은 경우에는 전역객체를 참조한다.
  • 생성자 함수에서의 this는 생성될 인스턴스를 참조한다.

2) 명시적 this바인딩

  • call,apply메서드는 this를 명시적으로 지정하면서 함수 또는 메서드를 호출한다.
  • bind메서드는 this 및 함수에 넘길 인수를 일부 지정해서 새로운 함수를 만든다.
  • 요소를 순회하면서 콜백 함수를 반복 호출하는 내용의 일부 메서드는 별도의 인자로 this를 받기도 한다.

[참고자료]
정재남, 『코어자바스크립트』, 위키북스(2019)
MDN - JavaScript, this
https://velog.io/@heo-mk/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8A%A4%ED%84%B0%EB%94%94-%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-3%EC%9E%A5-this
https://velog.io/@nayeon/Javascript%EC%97%90%EC%84%9C%EC%9D%98-this-%EC%99%80-call-apply-bind-%EB%A9%94%EC%84%9C%EB%93%9C

profile
해결문제에 대해 즐겁게 대화 할 수 있는 프론트엔드 개발자

0개의 댓글