Core JavaScript 6주차

Junyeol·2025년 9월 9일

Core JavaScript

목록 보기
7/8
post-thumbnail

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

call 메서드

  • 메서드의 호출 주제인 함수를 즉시 실행하도록 하는 명령이다.

  • call 메서드의 첫 번째 인자를 this로 바인딩하고, 이후의 인자들을 호출할 함수의 매개변수로 한다.

  • 함수를 그냥 실행하면 this는 전역객체를 참조하지만 call 메서드를 이용하면 임의의 객체를 this로 지정할 수 있다.

apply 메서드

  • apply 메서드는 call 메서드와 기능적으로 완전히 동일하다.

  • apply 메서드와 달리 두 번째 인자를 배열로 받아 그 배열의 요소들을 호출할 함수의 매개변수로 지정한다는 차이가 있다.

call / apply 메서드의 활용

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

  • 객체에는 배열 메서드를 직접 적용할 수 없다.

  • 키가 0 또는 양의 정수인 프로퍼티가 존재하고, length 프로퍼티의 값이 0 또는 양의 정수인 객체, 즉 배열의 구조와 유사한 객체의 경우 call or apply 메서드를 이용해 배열 메서드를 차용할 수 있다.

  • 7번째 줄에서는 배열 메서드인 push를 객체 obj에 적용해 프로퍼티 3에 'd'를 추가했다.

  • 9번째 줄에서는 slice 메서드를 적용해 객체를 배열로 전환했다.

  • slice는 원래 시작 인덱스값과 마지막 인덱스값을 받아 시작값부터 마지막값의 앞 부분까지의 배열요소를 추출하는 메소드인데, 매개변수를 아무것도 넘기지 않을 경우에는 그냥 원본 배열의 얕은 복사본을 반환한다.

  • 위 과정을 통해 원본인 유사배열객체의 얕은 복사를 slice 메서드를 통해 복사본을 배열로 반환하는 것이다.

  • 여기서 얕은 복사란?
    링크를 통해 설명을 추가 예정

  • 함수 내부에서 접근할 수 있는 arguments 객체도 유사배열 객체이므로 위의 방법으로 배열로 전환해서 활용할 수 있다.

  • querySelectorAll, getElementByvlassName 등의 Node 선택자로 선택한 결과인 NodeList도 마찬가지이다.

  • 이외에도 유사배열객체에는 call/apply 메서드를 이용해 모든 배열 메서드를 적용할 수 있다.

  • 배열처럼 인덱스와 length 프로퍼티를 지니는 문자열에 대해서도 마찬가지이다.

  • 단, 문자열의 경우 length 프로퍼티가 읽기 전용이기 때문에 원본 문자열에 변경을 가하는 메서드는 에러를 던지며, concat처럼 대상이 반드시 배열이어야 하는 경우에는 에러는 나지 않지만 제대로된 결과를 얻을수 없다.

  • 사실 call/apply를 이용해 형변환하는 것은 'this를 원하는 값으로 지정해서 호출한다' 라는 본래의 메서드의 의도와는 다소 동떨어진 활용법이라 할 수 있다.

  • slice 메서드는 오직 배열 형태로 '복사'하기 위해 차용됐을 뿐이다.

  • 이에 ES6에서는 유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환하는 Array.from 메서드를 새로 도입하였다.

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

  • 생성자 내부에 다른 생성자와 공통된 내용이 있을 경우 call or apply를 이용해 다른 생성자를 호출하면 간단하게 반복을 줄일 수 있다.

여러 인수를 묶어 하나의 배열로 전달하고 싶을 때 - apply 활용

  • 여러 개의 인수를 받는 메서드에게 하나의 배열로 인수들을 전달하고 싶을 때 apply 메서드를 사용하면 좋다.

  • 대표적으로는 최대/최솟 값을 구해야하는 경우에 사용하는데, Math.max / Math.min 메서드에 apply를 적용하여 코드를 작성할 수 있다.

  • ES6에서는 펼치기 연산자 (spread operatore)를 이용하면 apply를 적용하는 것 보다 더욱 간단하게도 작성할 수 있다.

bind 메서드

  • bind 메서드는 ES5에서 추가된 기능으로, call과 비슷하지만 즉시 호출하지는 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드이다.

  • 다시 새로운 함수를 호출할 때, 인수를 넘기면 그 인수들은 기존 bind 메서드를 호출할 때 전달했던 인수들의 뒤에 이어서 등록된다.

  • 즉 bind 메서드는 함수에 this를 미리 적용하는 것과 부분 적용 함수를 구현하는 두 가지 목적을 모두 가진다.

name 프로퍼티

  • bind 메서드를 적용해서 새로 만든 함수는 한 가지 독특한 성질이 있다.

  • 바로 name 프로퍼티에 동사 bind의 수동태인 'bound'라는 접두어가 붙는다.

  • 어떤 함수의 name 프로퍼티가 'bound xxx'라면 이는 곧 함수명이 xxx인 원본 함수에 bind 메서드를 적용한 새로운 함수라는 의미가 되므로 기존의 call이나 apply보다 코드를 추적하기에 더 수월하다.

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

  • 메서드의 내부함수에서 메서드의 this를 그대로 바라보게 하기 위한 방법으로 self 등의 변수를 활용한 우회법을 소개했었는데, call, apply or bind 메서드를 이용하여 더 깔끔하게 처리할 수 있다.

  • 또한 콜백 함수를 인자로 받는 함수나 메서드 중에서 기본적으로 콜백 함수 내에서의 this에 관여하는 함수 또는 메서드에 대해서도 bind 메서드를 이용하면 this 값을 사용자 맘대로 바꿀 수 있다.

화살표 함수의 예외사항

  • ES6에 새롭게 도입된 화살표 함수는 실행 컨텍스트 생성 시 this를 바인딩하는 과정이 제외됐다.

  • 즉 이 함수 내부에는 this가 아예 없으며, 접근하고자 하면 스코프체인상 가장 가까운 this에 접근하게 된다.

  • 화살표 함수로 구현하게 되면 별도의 변수로 this를 우회하거나 call / apply / bind를 적용할 필요가 없어 더욱 간결하고 편리하다.

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

  • 콜백 함수를 인자로 받는 메서드 중 일부는 추가로 this로 지정할 객체 (thisArg)를 인자로 지정할 수 있는 경우가 있다.

  • 이러한 메섣의 thisArg 값을 지정하면 콜백 함수 내부에서 this 값을 원하느 대로 변경할 수 있다.

  • 이런 형태는 여러 내부 요소에 대해 같은 동작을 반복 수행해야 하는 배열 메서드에 많이 포진되어 있다.



정리

명시적 this 바인딩이 없는 한 늘 성립하는 규칙

  • 전역공간에서의 this는 전역객체(브라우저에서는 window, Node.jsd에서는 global)를 참조한다.

  • 어떤 함수를 메서드로서 호출한 경우 this는 메서드 호출 주체(메서드명 앞의 객체)를 참조한다.

  • 어떤 함수를 함수로서 호출한 경우 this는 전역객체를 참조한다. 메서드의 내부함수도 동일하다.

  • 콜백 함수 내부에서의 this는 해당 콜백 함수의 제어권을 넘겨받은 함수가 정의한 바에 따르며, 정의하지 않은 경우에는 전역객체를 참조한다.

  • 생성자 함수에서의 this는 생성될 인스턴스를 참조한다.

명시적 this 바인딩이 있는 한 성립하는 규칙

  • call, apply 메서드는 this를 명시적으로 지정하면서 함수 또는 메서드를 호출한다.

  • bind 메서드는 this 및 함수에 넘길 인수를 일부 지정해서 새로운 함수를 만든다.

  • 요소를 순회하면서 콜백 함수를 반복 호출하는 내용의 일부 메서드는 별도의 인자로 this를 받기도 한다.

profile
천천히

0개의 댓글