코어 자바스크립트 스터디 3주차 - this

Genie·2021년 12월 2일
2

자바스크립트

목록 보기
4/4

회고
this 에 대해서 대답하기에는 다소 난해할 수 있었는데, 이번 장을 공부하면서 혼란스러웠던 개념을 이해하고, 몰랐던 call, apply 등에 대한 이해도 할 수 있었다.

상황에 따라 달라지는 this


  • 자바스크립트에서 this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정된다. 실행컨텍스트는 함수를 호출할 때 생성되므로, this는 함수를 호출할 때 결정된다.
  • this에는 호출한 주체에 대한 정보가 담긴다.


1. 전역 공간에서의 this


  • 전역 공간에서 this는 전역 객체를 가리킨다. 브라우저 환경에서 전역객체는 window , Node.js 환경에서는 global 이다.
  • 전역 변수를 선언하면 자바스크립트 엔진은 이를 전역객체의 프로퍼티로 할당한다는 건 몰랐는데 알게되었다.

  • 자바스크립트의 모든 변수는 실은 특정 객체의 프로퍼티로서 동작한다는 것을 알게되었다. 근데, let , const 변수는 실제 객체의 프로퍼티로서 동작할까? 에 대해서는 알아봐야 할 것 같다.

  • 전역 공간에서는 var로 변수를 선언한 것과 window 의 프로퍼티에 직접 변수를 할당하는 것은 대부분 같지만, 삭제 명령에 대해서는 다르다고 한다.
var a = 1;
delete window.a // false
delete a  // false

window.b = 2;
delete window.b // true
delete b // true
  • 이유는 바로, 전역변수를 선언할 때, 자바스크립트 엔진이 이를 자동으로 전역객체의 프로퍼티로 할당하면서 추가적으로 해당 프로퍼티의 configurable 속성(변경 및 삭제 가능성)을 false 로 정의하기 때문이다.



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


  • 자바스크립트에서 어떤 함수를 실행하는 방법은 여러 가지가 있는데, 일반적인 방법 두 가지는 함수로서 호출하는 경우와 메서드로서 호출하는 경우입니다.

  • 자바스크립트는 상황별로 this 키웟드에 다른 값을 부여하게 함으로써 독립성을 구현함.

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

  • 그렇다면, 함수로서 호출 과 메서드로서 호출 을 어떻게 구분할까요?

    • 함수 앞에 점(.) 이 있는지 여부로 간단히 구분할 수 있다.
    • 점이 없으면 함수로서 호출한 것 , 점이 있으면 메서드로서 호출한 것

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


  • 함수 내부에서의 this
    • 개발자가 코드에 직접 관여해서 실행한 것이기 때문에 호출 주체의 정보를 알 수 없다. 따라서, 함수에서의 this 는 지정되지 않은 경우 전역 객체를 바라보기 때문에 전역 객체를 가리킨다.
  • 메서드의 내부함수에서의 this
    • 내부함수 역시, 이를 함수로서 호출했는지 메서드로서 호출했는지만 파악하면 this의 값을 정확히 맞출 수 있다.
  • this를 바인딩하지 않는 함수
    • 화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 빠지게 되어, 상위 스코프의 this를 그대로 활용할 수 있다.
  • 참고
    • 내부함수에서의 this를 우회하는 방법 ( 변수를 활용하자! )
    • 주로 self 를 많이 활용한다.
var obj = {
	outer : function () {
            var self = this;
            var innerFunc = function () {
                console.log(self); // {outer: f}
            };
            innerFunc();
	}
}
obj.outer();

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


  • 콜백 함수 : 함수 A의 제어권을 다른 함수(또는 메서드) B에게 넘겨주는 경우 함수 A를 콜백 함수라 합니다.

  • 콜백 함수에서의 this 는 콜백 함수의 제어권을 가지고 있는(B) 가 콜백 함수에서의 this 를 무엇으로 할지를 결정하며, 특별히 정의하지 않은 경우에는 기본적으로 함수와 마찬가지로 전역 객체를 바라보도록 되어있다.

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


  • 어떤 함수가 생성자 함수로서 호출된 경우 내부에서의 this는 곧 새로 만들 구체적인 인스턴스 자신이 됩니다.
  • 생성자 함수를 호출하면, 생성자의 prototype 프로퍼티를 참조하는 __proto__ 라는 프로퍼티가 있는 객체(인스턴스) 를 만들고, 미리 준비된 공통 속성 을 해당 객체(this)에 부여합니다.

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

1. call 메서드

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

2. apply 메서드

apply 메서드는 call 메서드와 기능적으로 동일한데, 두 번째 인자를 배열로 받아 그 배열의 요소들을 호출할 함수의 매개변수로 지정한다.

3. call/apply 메서드의 활용

유사배열객체에 배열 메서드를 적용할 수 있다.

유사 배열 객체 : 키가 0 또는 양의 정수인 프로퍼티가 존재하고, length 프로퍼티의 값이 0 또는 양의 정수인 객체

위의 length : 3 이런 속성이 없으면 빈 배열로 나옴. console.log(arr);


생성자 내부에서 다른 생성자를 호출할 수 있다.

생성자 내부에 다른 생성자와 공통된 내용이 있을 경우, call 또는 apply 를 이용해 다른 생성자를 호출할 수 있다.


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

var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);

ES6 에서는 펼치기 연산자를 활용하면 간단해진다.

const max = Math.max(...numbers);

4. bind 메서드

ES5 에서 추가된 기능으로, 새로운 함수를 반환하기만 하는 메서드
함수에 this를 미리 적용하는 것이 가능하고, 부분 적용 함수를 구현할 수 있다.

var bindFunc1 = func.bind({ x:1 });
bindFunc1(5,6,7,8); // {x : 1} 5 6 7 8

var bindFunc2 = func.bind({x:1} , 4, 5);
console.log(bindFunc2.name); // bound func 라고 출력됨.
bindFunc2(6,7); // {x : 1} 4 5 6 7
bindFunc2(8,9); // {x: 1 } 4 5 8 9

bind 를 이용하여 명확하게 this 를 바인딩 시킬 수 있다.

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

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

6. 별도의 인자로 this를 받는 경우

콜백 함수를 인자로 받는 메서드 중 일부는 추가로 this로 지정할 객체(thisArg)를 인자로 지정할 수 있는 경우가 있다.
주로, 배열 메서드에 많이 존재하고, Set, Map 등의 메서드에도 존재한다.

Array.prototype.forEach(callback[, thisArg]);
Array.prototype.map(callback[, thisArg]);
Array.prototype.filter(callback[, thisArg]);
profile
차근차근

0개의 댓글