this

Seunghyo Ku·2021년 5월 17일
0

JavaScript

목록 보기
3/3

이번 장에서는 this에 대해 살펴봅니다.

  • this가 어떻게 쓰이는지
  • 함수와 객체(메서드)가 어떻게 구분되는지

를 중심으로 살펴봅니다.

여러 상황 속에서의 this

this는 실행컨텍스트가 생성될 때 함께 결정됩니다.

이전 장에서 보았듯이 생성 컨텍스트는 함수를 호출할 때 생성되기 때문에, 결국 this는 함수를 호출할 때 결정됩니다.

전역 공간, 메서드 내부, 함수 내부, 콜백 함수 내부, 생성자 함수 내부에서의 this를 차례로 살펴보겠습니다.

1. 전역 공간

전역 공간의 this는 전역 객체를 기킵니다.

전역 객체는 런타임 환경에 따라 다릅니다.

  • 브라우저: window
  • Node.js: global

사실 자바스크립트의 모든 변수는 특정 객체의 프로퍼티로 동작하며, 특정 함수 호출 시 LE(Lexical Environment)를 조회하여 일치하는 프로퍼티를 반홥합니다.

전역변수를 선언하면 자바스크립트 엔진은 전역객체의 프로퍼티로 할당하기 때문에 전역 변수인 a를 window.a 와 this.a로 호출했을 때 같은 결과를 볼 수 있습니다. 그냥 a만 작성하였을 때도 같은 결과를 볼 수 있는 까닭은, 스코프 체인에서 a를 찾다가 마지막 전역 LE (전역 객체)에서 프로퍼티 a를 발견해서 반환하기 때문입니다. 이 경우 생략되었다고 볼 수 있습니다.

이걸 이용해서 삭제 하면 어떻게 해요?

전역 객체의 프로퍼티로 할당한 경우 삭제가 되지만, 전역 변수로 선언한 경우는 삭제가 되지 않습니다. 이를 통해 사용자가 삭제 하는 것을 방지할 수 있습니다. 전역 변수 선언시 전역객체 프로퍼티로 선언하며 configurable: false로 지정해주기 때문입니다. 이를 통해 변경 및 삭제를 막을 수 있습니다.

2. 메서드 호출 시 메서드 내부의 this

함수냐 메서드냐

함수와 메서드는 모두 미리 정의한 동작을 수행하는 코드 묶음입니다. 이 둘의 구분은 독립성으로 확인할 수 있습니다.

  • 함수: 그 자체로 독립적인 기능을 수행
  • 메서드: 자신을 호출한 대상 객체에 관한 동작 수행

코드로 살펴보면 다음과 같습니다.

// 함수
var func = function(x) {
	console.log(this, x);
}
// 함수 호출
func(1); 
// 메서드
var obj = {
	method: func
};
// 메서드 호출
obj.method(2);

즉, 메서드는 객체의 메서드로서 호출할 경우 메서드로 동작하고 있습니다. 그렇지 않을 경우 일반 함수(func)으로 동작하는 것을 확인할 수 있습니다.

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

  • 함수 내부에서의 this

    함수로 호출할 떄는 this가 지정이 되지 않습니다. 호출 주체(여기서는 객체)에 대한 정보가 this에 담기기 때문입니다. this가 지정되지 않은 경우에는 전역 객체를 가리키기 때문에 함수에서의 this는 전역 객체를 가리키게 됩니다.

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

    호출한 함수 프로퍼티 앞의 객체를 가리킵니다.

    (점 표기법의 경우 마지막 점 바로 앞의 명시된 객체를 의미합니다.)

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

    JS의 설계 때문에 우회적으로 변수를 활용해 this를 사용할 수 있습니다.

    var obj = {
    	var outer : function () {
    		var self = this; // _, _this, that 등이 변수로 쓰임
    		var innerFunc = function () {
    			console.log(this); // Window {..} 전역
    			console.log(self); // outer: f	
    		}		
    	}
    }
  • this를 바인딩하지 않는 화살표 함수

    ES6에서는 함수 내부의 this가 전역개체를 바라보는 것을 해결하기 위해 this를 바인딩하지 않는 화살표 함수가 나왔습니다. 화살표 함수는 this 바인딩 과정이 빠져, 가장 가까운 상위 스코프의 this를 활용할 수 있습니다.

콜백함수 내부에서의 this

  • 콜백 함수란?

    함수의 제어권을 다른 함수(또는 메서드)에 넘겨주는 경우.

    제어권을 넘겨준 함수를 콜백 함수라고 합니다.

콜백함수에서는 제어권을 가지는 함수가 콜백 함수에서의 this를 결정하며, 만약 지정하지 않은 경우에는 기본적인 함수와 마찬가지로 전역 객체를 바라보게 됩니다.

생성자 함수 내부에서의 this

  • 생성자 함수란?

    공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수

생성자 함수 내부의 this는, 각 인스턴스 객체를 가리킵니다.

명시적으로 this 바인딩하기

이 외에도 call, apply, bind 함수를 이용하여 명시적으로 대상을 바인딩 할 수 있습니다.

차례대로 살펴보겠습니다.

call

Function.prototype.call(thisArg[, arg1[,...]])

메서드의 호출 주체인 함수를 즉시 실행합니다.

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

var func = function (a, b, c) {
	console.log(this, a, b, c);
};

func(1, 2, 3) // Window{..} 1 2 3
func.call({ x : 1 }, 4, 5, 6}; // { x : 1 } 4 5 6

apply

Function.prototype.apply(thisArg[, arg1[,...]])

call 메서드와 기능적으로 동일하나, 두 번째 인자를 배열로 받아 매개변수로 지정한다는 점에서 차이가 있습니다.

var func = function (a, b, c) {
	console.log(this, a, b, c);
};

func.apply({x: 1}, [4, 5, 6]); // {x: 1} 4 5 6

call/apply의 활용

  • 유사 배열객체(array-like object)에 배열 메서드 적용

    var obj = {
    0: 'a',
    	1: 'b',
    	2: 'C',
    	length: 3
    };
    
    Array.prototype.push.call(obj, 'd'); // 3 자리에 d들어감
    var arr = Array.prototype.slice.call(obj); // 얕은 복사 - ['a', 'b', 'c', 'd'];
    • arguments, NodeList에 배열 메서드 적용

    • 문자열에 배열 메서드 적용

    • Array.from 메서드

      유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환할 수 있습니다.

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

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

bind

Function.prototype.bind(thisArg, [, arg1,...]])

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

var func = function (a, b, c, d) {
	console.log(this, a, b, c, d);
};

func(1, 2, 3, 4); // 전역

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);
bindFunc2(6, 7); // { x: 1 } 4 5 6 7
  • name프로퍼티를 사용하여 원본 함수를 추적할 수 있습니다.
console.log(func.name); // func
console.log(bindFunc2.name); // bound func

콜백함수 내에서의 this

콜백함수와 함께 thisArg를 인자로 받는 메서드는 다음과 같습니다.

  • forEach, map, filter, some, every, find, findIndex, flatMap, from, forEach(Set, Map에 해당)
profile
꼬꼬마 개발자 구승효입니다!

0개의 댓글