ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [코어 자바스크립트 북스터디 3주차] 3장. this
    📝 기록/독서 기록 2021. 12. 2. 22:27

    ✅ 삼색 볼펜법 활용
    빨간색: 핵심내용
    파란색: 핵심은 아니지만 중요하다고 생각되는 내용
    초록색: 흥미로운 내용

    3장 this

    다른 대부분의 객체지향 언어에서 this는 클래스로 생성한 인스턴스 객체를 의미한다.
    클래스에서만 사용할 수 있기 때문에 혼란의 여지가 거의 없다.

    반면에, 자바스크립트에서의 this는 어디서든 사용할 수 있다.
    상황에 따라 this가 바라보는 대상이 달라지는데,
    - 어떤 이유로 그렇게 되는지를 파악하기 힘든 경우
    - 예상과 다르게 엉뚱한 대상을 바라보는 경우
    등이 있다.

    1. 상황에 따라 달라지는 this

    자바스크립트에서 this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정된다.
    실행 컨텍스트는 함수를 호출할 때 생성된다. 즉, this는 함수를 호출할 때 결정된다.

    함수를 어떤 방식으로 호출하느냐에 따라 값이 달라지는 것.

    1-1. 전역 공간에서의 this

    전역 공간에서 this는 전역객체를 가리킨다.

    개념상 전역 컨텍스트를 생성하는 주체가 바로 전역객체이기 때문.
    전역객체는 자바스크립트 런타임 환경에 따라 다른 이름과 정보를 가지고 있다.
    브라우저 환경: window
    Node.js 환경: global

    전역변수를 선언하면 자바스크립트 엔진은 이를 전역객체의 프로퍼티로도 할당한다.
    변수이면서 객체의 프로퍼티이기도 한 셈.

    자바스크립트의 모든 변수는 실은 특정 객체의 프로퍼티로서 동작한다.
    사용자가 var 연산자를 이용해 변수를 선언하더라도 실제 자바스크립트 엔진은 어떤 특정 객체의 프로퍼티로 인식하는 것.

    정확한 표현: 전역 변수를 선언하면 자바스크립트 엔진은 이를 전역객체의 프로퍼티로 할당한다.

    또한 처음부터 전역객체의 프로퍼티로 할당한 경우에는 삭제가 되는 반면,
    전역변수로 선언한 경우에는 삭제가 되지 않는 것을 확인할 수 있다.
    → 사용자가 의도치 않게 삭제하는 것을 방지하는 차원에서 마련한 것.

    전역변수로 선언하면 자바스크립트 엔진이 이를 자동으로 전역객체의 프로퍼티로 할당하면서 추가적으로 해당 프로퍼티의 configurable 속성(변경 및 삭제 가능성)을 false로 정의하는 것.

    1-2. 메서드로서 호출할 때 그 메서드 내부에서의 this

    함수 vs. 메서드

    어떤 함수를 실행하는 방법 중 가장 일반적인 방법 두 가지
    1. 함수로서 호출하는 경우
    2. 메서드로서 호출하는 경우

    이 둘을 구분하는 유일한 차이는 독립성에 있다.
    함수는 그 자체로 독립적인 기능을 수행하는 반면,
    메서드는 자신을 호출한 대상 객체에 관한 동작을 수행한다.

    어떤 함수를 객체의 프로퍼티에 할당한다고 해서 그 자체로서 무조건 메서드가 되는 것이 아니라 객체의 메서드로서 호출할 경우에만 메서드로 동작하고, 그렇지 않으면 함수로 동작한다.

    '함수로서 호출'과 '메서드로서 호출'을 어떻게 구분할까? 함수 앞에 점(.)이 있는지 여부만으로 간단하게 구분할 수 있다.

    점 표기법이든 대괄호[] 표기법이든, 어떤 함수를 호출할 때 그 함수 이름(프로퍼티명) 앞에 객체가 명시되어 있는 경우에는 메서드로 호출한 것이고, 그렇지 않은 모든 경우에는 함수로 호출한 것.

    메서드 내부에서의 this

    this에는 호출한 주체에 대한 정보만 담긴다.
    어떤 함수를 메서드로서 호출하는 경우 호출 주체는 바로 함수명(프로퍼티명) 앞의 객체.

    1-3. 함수로서 호출할 때 그 함수 내부에서의 this

    함수 내부에서의 this

    어떤 함수를 함수로서 호출할 경우에는 this가 지정되지 않음
    → 함수로서 호출하는 것은 호출 주체(객체 지향 언어에서의 객체)를 명시하지 않고, 개발자가 코드에 직접 관여해서 실행한 것이기 때문에 호출 주체의 정보를 알 수 없는 것

    메서드의 내부함수에서의 this

    this바인딩에 관해서는 함수를 실행하는 당시의 주변 환경(메서드 내부인지, 함수 내부인지 등)은 중요하지 않고, 오직 해당 함수를 호출하는 구문 앞에 점 또는 대괄호 표기가 있는지 없는지가 관건

    메서드의 내부함수에서의 this를 우회하는 방법

    아쉽게도 ES5까지는 자체적으로 내부 함수에 this를 상속할 방법이 없지만, 우회할 수는 있다.
    대표적인 방법으로는 변수를 활용하면 된다.

    그저 상위 스코프의 this를 저장해서 내부 함수에서 활용하려는 수단일 뿐.

    this를 바인딩하지 않는 함수

    ES6에서는 함수 내부에서 this가 전역 객체를 바라보는 문제를 보완하고자, this를 바인딩하지 않는 화살표 함수를 새로 도입함

    1-4. 콜백 함수 호출 시 그 함수 내부에서의 this

    콜백 함수: 함수 A의 제어권을 다른 함수(또는 메서드) B에게 넘겨주는 경우, 함수 A를 콜백 함수라 지칭한다.
    이때 함수 A는 함수 B의 내부 로직에 따라 실행되며, this 역시 함수 B 내부 로직에서 정한 규칙에 따라 값이 결정된다.
    즉, 콜백 함수의 제어권을 가지는 함수(메서드)가 콜백 함수에서의 this를 무엇으로 할지를 결정하며, 특별히 정의하지 않은 경우에는 기본적으로 함수와 마찬가지로 전역 객체를 바라본다.

    1-5. 생성자 함수 내부에서의 this

    생성자 함수는 어떤 공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수다.
    객체 지향 언어에서는 생성자를 클래스, 클래스를 통해 만든 객체를 인스턴스라고 한다.

    프로그래밍적으로 '생성자'는 구체적인 인스턴스를 만들기 위한 일종의 틀이다.

    자바스크립트는 함수에 생성자로서의 역할을 함께 부여한다.
    new 명령어와 함께 함수를 호출하면 해당 함수가 생성자로서 동작하게 된다.
    또한 어떤 함수가 생성자 함수로서 호출된 경우, 내부에서의 this는 곧 새로 만들 구체적인 인스턴스 자신이 된다.

    인스턴스가 만들어지는 과정
    1. 생성자 함수를 호출(new 명령어와 함께 함수를 호출)
    2. 생성자의 prototype 프로퍼티를 참조하는 __proto__라는 프로퍼티가 있는 객체(인스턴스)를 생성
    3. 미리 준비된 공통 속성 및 개성을 해당 객체(this)에 부여

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

    2-1. call 메서드

    call 메서드: 메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령
    이때 call 메서드의 첫 번째 인자를 this로 바인딩하고, 이후의 인자들을 호출할 함수의 매개변수로 함.

    메서드에 대해서도 똑같이 객체의 메서드를 그냥 호출하면 this는 객체를 참조하지만, call메서드를 이용하면 임의의 객체를 this로 지정할 수 있다. 

    2-2. apply 메서드

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

    2-3. call / apply 메서드의 활용

    1. 유사 배열 객체에 배열 메서드를 적용
    2. 
    생성자 내부에서 다른 생성자를 호출
    3. 
    여러 인수를 묶어 하나의 배열로 전달하고 싶을 때

    2-4. bind 메서드

    bind 메서드: call과 비슷하나 즉시 호출하지 않고 넘겨 받은 this 및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드

    bind 메서드의 목적
    1. 함수에 this를 미리 적용하는 것
    2. 부분 적용 함수를 구현하는 것

    name 프로퍼티

    bind 메서드를 적용해서 새로 만든 함수는 name 프로퍼티에 동사 bind의 수동태인 'bound'라는 접두어가 붙음

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

    1-3에서 변수를 활용하여 우회하는 방법도 있지만, call, apply, bind 메서드를 사용하면 더 깔끔하게 처리 가능.

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

    2-5. 화살표 함수의 예외사항

    화살표 함수 내부에는 this가 아예 없으며, 접근하고자 하면 스코프체인 상 가장 가까운 this에 접근하게 됨

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

    콜백 함수를 인자로 받는 메서드 중 일부는 추가로 this로 지정할 객체(thisArg)를 인자로 지정할 수 있는 경우가 있다.
    - forEach
    - map
    - filter
    - some
    - every
    - find
    - findIndex
    - flatMap
    - from

    3주 차 회고

    항상 무심하게 지나쳤던 개념들을 정확하게 공부할 수 있었던 시간이었던 것 같다. 예를 들면 bind(this), 내부 함수에서의 this를 우회하는 방법(var self = this;)이라든지...
    확실히 같은 공부를 하시는 분들이랑 이렇게 시간 맞춰 책 읽고, 생각 공유하고, 블로그 정리까지 하는 게 굉장히 유의미한 것 같다.
    스터디원 분 중에 한 분은 면접 때 스터디에서 얘기했던 내용이 나왔어서 자신 있게 대답하셨다는...☺️
    나도 열심히 공부해서 면접 뿌셔야지..! 💪