누가봐도 인생 1회차의 기록장

개발공부/JavaScript 책

코어 자바스크립트 #04 (this - 2 명시적으로 this를 바인딩하는 방법)

김놀먹 2021. 12. 2. 19:57

call 메서드

메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령. 이때 call 메서드는 첫 번째 인자를 this로 바인딩하고, 이후의 인자들을 호출할 함수의 매개변수로 한다. 함수를 그냥 실행하면 this는 전역객체를 참조하지만 call 메서드를 이용하면 임의의 객체를 this로 지정할 수 있다. (메서드도 동일. 그냥 호출하면 this는 객체 참조, call 메서드를 이용하면 임의의 객체를 this로 지정)

apply 메서드

call 메서드와 기능적으로 완전히 동일하지만 call 메서드는 첫번째 인자를 제외한 나머지 모든 인자들을 호출할 함수의 매개변수로 지정하는 반면, apply 메서드는 두 번째 인자를 배열로 받아 그 배열의 요소들을 호출할 함수의 매개변수로 지정한다. 

call / apply 메서드의 활용

  • 유사배열객체array-like object 에 배열 메서드 적용 : 객체에는 배열 메서드를 직접 적용할 수 없다. 하지만 키가 0 또는 양의 정수인 프로퍼티가 존재하고 length 프로퍼티 값이 0 또는 양의 정수인 객체, 즉 배열의 구조와 유사한 객체의 경우(유사배열객체) call, apply 메서드를 이용하여 배열 메서드를 차용할 수 있다. 단, 문자열일 경우 length 프로퍼티가 읽기 전용이기 때문에 원본 문자열에 변경을 가하는 메서드 (push, pop, shift, unshift, splice 등)는 에러를 던지며, concat처럼 대상이 반드시 배열이어야 하는 경우에는 에러는 나지 않지만 제대로 된 결과를 얻을 수 없다. 
  • 생성자 내부에서 다른 생성자를 호출 : 생성자 내부에 다른 생성자와 공통된 내용이 있을 경우 call 또는 apply를 이용해 다른 생성자를 호출하면 간단하게 반복을 줄일 수 있다. 
  • 여러 인수를 묶어 하나의 배열로 전달하고 싶을 때 - apply 활용

bind 메서드

ES5에서 추가된 기능으로, call과 비슷하지만 즉시 호출하지는 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드. 다시 새로운 함수를 호출 할 때 인수를 넘기면 그 인수들은 기존 bind 메서드를 호출할 때 전달했던 인수들의 뒤에 이어서 등록된다. 즉, bind 메서드는 함수에 this를 미리 적용하는 것과 부분 적용함수를 구현하는 두 가지 목적을 모두 지닌다

  • name 프로퍼티 : bind 메서드를 적용해서 새로 만든 함수는 name 프로퍼티에 'bound'라는 접두어가 붙는다는 독특한 성질이 있다. 어떤 함수의 name 프로퍼티가 'bound xxx'라면 함수명이 xxx인 원본 함수에 bind 메서드를 적용한 새로운 함수라는 의미가 되므로 기존의 call이나 apply 보다 코드를 추적하기 수월하다. 
  • 상위 컨텍스트의 this를 내부함수나 콜백 함수에 전달하기 

화살표 함수의 예외사항

ES6에 도입된 화살표 함수는 실행 컨텍스트 생성 시 this를 바인딩하는 과정이 제외됐다. 즉, 이 함수 내부에는 this가 아예 없으며, 접근하고자 하면 스코프체인상 가장 가까운 this에 접근하게 된다.

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

콜백 함수를 인자로 받는 메서드 중 일부는 추가로 this로 지정할 객체 (thisArg)를 인자로 지정할 수 있는 경우가 있다. 이러한 메서드의 thisArg값을 지정하면 콜백 함수 내부에서 this 값을 원하는 대로 변경할 수 있다. 이런 형태는 여러 내부 요소에 대해 같은 동작을 반복 수행해야 하는 배열 메서드에 많이 포진돼 있으며, 같은 이유로 ES6에서 새로 등장한 set, map 등의 메서드에도 일부 존재한다.