this | 코어자바스크립트 3

deli-ght·2022년 3월 21일
3

Javascript / algorithm

목록 보기
10/14
post-thumbnail

다른 대부분의 객체지향 언어에서 this는 클래스로 생성한 인스턴스 객체
하지만 자바스크립트에서는 클래스의 개념이 없었기 때문에 (ES6부터 존재) this는 어디서든 사용할 수 있음
특히 자바스크립트에서 this는 애매모호한 함수와 객체(메서드)를 구분하는 유일한 기능

상황에 따라 달라지는 this

자바스크립트에서 this는 실행 컨텍스트가 생성될 때 함께 결정됨.
실행 컨텍스트가 생성될 때 == 함수를 호출할 때
따라서 this는 함수를 호출할 때 결정.

전역 공간에서의 this

전역 공간에서 this = 전역 객체
런타임 환경에 따라 전역 객체가 무엇인지 결정 됨.
브라우저 환경 : window
node.js : global

전역 변수를 선언하면 자바스크립트 엔진은 이것을 전역 객체의 프로퍼티로 할당
자바스크립트의 모든 변수는 실은 특정 객체의 프로퍼티로 동작

하지막 삭제 명령에서 차이를 보이는데,

  • 전역객체의 프로퍼티로 할당한 경우에는 삭제가 되는 반면
  • 전역변수로 설정한 경우에는 삭제가 되지 않음.

var로 선언한 전역 변수와 전역 객체의 프로퍼티는 호이스팅 여부 및 configurable(변경 및 삭제 가능성) 여부에서 차이를 보임

메서드로서 호출할 때 그 내부에서의 This

함수 vs 메서드

어떤 함수를 실행하는 방법
1. 함수로서 호출
2. 메서드로서 호출

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

어떤 함수를 호출할 때 그 함수 이름 앞에 객체가 명시되어 있다면 메서드 호출
그게 아닌 모든 경우엔 함수 호출

메서드 내부에서의 this

this : 호출한 주체(함수명 앞의 객체)에 대한 정보가 담김

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

함수 내부에서의 this

함수의 this == 전역객체

메서드 내부 함수에서의 this

this 바인딩에 관해서 함수를 실행하는 당시의 주변 환경은 중요하지 않고
해당 함수를 호출하는 구문 앞에 점 또는 대괄호 표기의 유무에 따라 결정됨.

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

현재 컨텍스트에 바인딩된 대상이 없으면 직전 컨텍스트의 this를 바라보도록 하는 방법

ES5

자체적으로 내부 함수에 this를 상속할 방법이 없음
대표적으로 우회하는 방법 = 변수를 활용하는 방법


(let으로 적용해도 같은 결과 출력)

상위 스코프의 this를 저장해 내부 함수에서 활용하려는 수단으로 self를 사용

ES6 : this를 바인딩하지 않는 함수

ES6에서는 위와 같은 문제를 보완하고자 this를 바인딩하지 않는 화살표 함수를 도입

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

콜백함수 : 본인의 제어권을 다른 함수 b에게 넘겨주는 함수
이 때, this는 함수 B의 로직에서 정한 규칙에 따라 값이 결정됨.
특별히 정의하지 않는 경우, 기본적으로 함수와 마찬가지로 this = 전역객체

생성자 함수 내부에서의 this

생성자 함수 : 어떤 공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수
프로그래밍적으로 생성자는 구체적인 인스턴스를 만들기 위한 틀

자바스크립트에서는 함수에 생성자의 역할 부여
new 명령어와 함께 함수 호출시, 해당 함수는 생성자로서 동작
이 때, 내부에서의 this는 새로 만들 구체적인 인스턴스 자신

<인스턴스 생성 과정>

생성자 함수를 호출
-> 생성자의 prototype 프로퍼티를 참조하는 __proto__라는 프로퍼티가 있는 객체 생성
-> 미리 준비된 공통 속성을 해당 객체(this)에 부여

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

call()

메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령
call(this로 바인딩 되는 인자, 호출할 함수의 매개변수)

함수를 그냥 실행 시, this는 전역 객체를 참조

임의의 객체를 this로 지정할 수 있음.
메서드에 대해서도 마찬가지로 원하는 객체를 this로 지정할 수 있음.

apply()

call 메서드와 기능적으로 동일
차이점은 두번째 인자를 배열로 받아 호출할 함수의 매개변수로 지정

call/ apply 메서드를 활용하는 방법

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

객체에는 배열 메서드를 적용할 수 없음.
하지만 key가 0 또는 양의 정수인 프로퍼티가 존재하고, length 프로퍼티의 값이 0 또는 양의 정수인 객체를 배열 메서드를 차용할 수 있음.

Array.prototype.slice.call(유사배열객체) 로 유사배열객체를 배열로 복사해줌
배열로 복사해주는 역할을 하기 때문에 원본 배열을 수정하는 메서드 사용시 에러 발생

이를 보완하기 위해 ES6에서는 Array.from()메서드를 도입
Array.from(obj)

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

클래스의 super와 같은 역할로 동작

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

ES6에서는 스프래드 문법을 사용하여 표현할 수 있음

let max = Math.max.apply(null, numbers)
let max = Math.max(...numbers);

bind()

ES5에서 추가된 기능으로 즉시 호출하지 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하는 메서드
다음의 기능들을 구현하는 목적을 지님

  • 함수에 this를 미리 적용
  • 부분 적용 함수 구현

name 프로퍼티

bind 메서드를 적용해 만들어진 함수는 name 프로퍼티에 bound라는 접두사가 붙는 성질을 가짐
이 성질을 이용해 해당 함수가 bind 메서드에 의해 만들어진 함수라는 것을 알 수있음.

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


// call 사용 - 원본 배열에 this 값을 넘겨주기
let obj = {
  outer : function() {
    console.log(this);
    let innerFunc = function(){
      console.log(this);
    }
    innerFunc.call(this)
  }
}

obj.outer();

//bind 사용 - this값이 넘겨진 새로운 배열 리턴하기
let obj = {
  outer : function() {
    console.log(this);
    let innerFunc = function(){
      console.log(this);
    }.bind(this);
    innerFunc();
  }
}

obj.outer();

화살표 함수의 예외사항

화살표 함수 : 실행 컨텍스트 생성시 this를 바인딩하는 과정이 제외
이 함수 내에는 this가 존재 X, 스코프체인상 가장 가까운 this에 접근

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

콜백함수를 인자로 받는 메서드 중 일부는 추가로 this로 지정할 객체를 인자로 지정할 수 있는 경우가 있음.
주로 내부 요소에 대해 같은 동작을 반복해야하는 배열 메서드에 많이 포진
아래의 함수들은 (콜백함수, this) 형식의 매개변수를 가짐

  • forEach
  • map
  • filter
  • some
  • every
  • find
  • findIndex
  • flatMap
  • from
  • Set.prototype.forEach
  • Map.prototype.forEach
profile
PRE-FE에서 PRO-FE로🚀🪐!

4개의 댓글

comment-user-thumbnail
2022년 3월 21일

자바스크립트 전문가 ,,,

1개의 답글
comment-user-thumbnail
2022년 3월 23일

저도 곧 this 공부하고 글 올릴 예정~

1개의 답글