본문 바로가기

자바스크립트

[javascript] this 는 호출하는 방식에 따라 가리키는 대상이 달라진다.

반응형

this... this.. this..

자바스크립트에서 this는 함수를 호출하는 방식에 따라서 가리키는 대상 혹은 값이 달라진다.

대표적으로 일반함수(function), 생성자 함수, 메서드 3 가지 방식에 따라 나뉜다. 오늘은 이 3가지 방식을 구분해서 정리해보고, 다음 시간에는 this 가 가리키는 대상을 강제적으로 어떻게 바꿀 수 있는가에 대해서도 정리할 것이다.


일반 함수에서의 this

여기서 말하는 일반함수는 흔히 자주 쓰이는 function(){ } 을 말한다.
일반함수에서 this 는 언제나 전역 객체를 가리키는데, 전역 객체는 자바스크립트에서 최상위 객체를 의미한다.

(참고) 전역 객체

자바스크립트의 대부분은 객체로 구성되어 있다. 그 객체를 모두 포괄하는 최상위 객체를 전역 객체라고 한다.
브라우저(즉, 우리가 쓰는 인터넷 환경)에서는 window 객체를 의미하고, node.js 환경에서는 global 객체를 의미한다.

참고로 전역 객체를 가리키는 것은 함수 내부에서 뿐이 아니다. 다음과 같이 변수와 함수를 선언해서 this 키워드를 사용해보면 모두 전역 객체를 가리키는 것을 알 수 있다.

// 함수 내에서 this 
function windowThis(){
    console.log('함수 내:',this)
}
windowThis();

// 전역에서 this 
console.log('전역에서:',this);


//출력결과)
함수 내: Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, …}
전역에서: Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, …}

 

일반함수에서의 this는 간혹 혼란을 야기한다. 즉, 함수의 컨텍스트(전역인지 아닌지)가 어디인지 명확히 알 수 없기 때문이다. 그래서 이러한 문제를 사전에 차단하기 위해서 혹은 명확한 용도로 지정해두기 위해서 'use strict' 라는 엄격 모드를 함수 내부의 최상단에 입력하여 사용한다. 그렇게 되면 함수 내부에서 this는 전역 객체를 가리키는 것이 아니라 엄격한 기준에 따라 undefined 로 남게 된다. (엄격 모드는 this 문제 외에도 타입에러나 기타 에러 등을 사전에 탐지하여 예방할 수 있도록 해주기 때문에 유용하다.)


생성자 함수에서의 this

생성자 함수는 new 키워드를 이용해 함수를 호출하는 순간 일반 함수에서 변환되어 만들어지는 함수이다.

또한, 생성자 함수는 객체를 대량으로 생성토록 해주는 함수(말 그대로 객체를 찍어내는 공장 같은 것)이다. 이러한 특성을 지닌 생성자 함수는 앞서 일반함수와는 this가 다르게 동작한다.

생성자 함수에서 this는 생성자 함수가 생성될 때 만들어지는 객체를 가리킨다.

즉, 아래 코드에서는 보이지 않지만 함수의 최상단에는 보이지 않는 객체가 생성되고, this는 그 객체를 가리키게 된다.

이에 대해 코드로 설명해보면 다음과 같다.

function Human(name,age){
 // new 이용 시 보이지 않지만 빈 객체인 Human ={}가 생성
 // this 는 Human ={} 을 가리킨다.
 // 빈 객체의 프로퍼티로 추가되어 온전한 객체가 생성된다
    this.name = name
    this.age = age
}

const manA = new Human('kin',40); //manA 라는 Human 객체가 생성되었다.
const manB = new Human('lee',105); //manB 라는 Human 객체가 생성되었다.

여기서 this 는 위에서 생성된 각각의 객체를 가리킨다.

즉, 생성자 함수에서의 this 는 각각 new 키워드를 통해 생성된 객체를 따로 가리키게 된다.

(참고) 생성자 함수를 통해 생성된 객체를 인스턴스 라고 한다.

(궁금하면 클릭) 일반적인 객체리터럴과 어떤 차이가 있을까?

더보기

일반적인 객체 리터럴은 객체를 생성하려면 각각 내부 프로퍼티와 값을 지정해줘야 한다. 그래서 키는 같은 데 값은 서로 다른 정보들이 있으면 그것을 만들기 위해서 아래와 같이 객체1, 객체2를 새롭게 몽땅 그려줘야 한다.

const obj1 = {
 // ...
}

const obj2 = {
 // ...
}

 

그러나, 생성자 함수는 설계도를 함수 내에 만들어두는 것과 같다. 즉, 객체 리터럴은 설계도면 없이 즉흥적으로 계속 물건을 만들어 내는 것이라면,

 

생성자 함수는 설계도면을 만들어 놓고, 필요한 물건들이 있으면 도면에 따라서 뚝딱뚝딱 만들어 내는 것과 같다

앞서 생성자 함수의 예시를 살펴봐도 알겠지만, 아래와 같이 new 키워드로 인스턴스에 들어갈 인자만 다르게 해서 함수의 매개변수로 전달해주기만 하면, 각각 다른 객체를 빠르고 정확하게 만들 수 있다.

function Human(name,age){
    this.name = name
    this.age = age
}

const manA = new Human('kin',40); //manA 라는 Human 객체가 생성되었다.
const manB = new Human('lee',105); //manB 라는 Human 객체가 생성되었다.

 

그래서 대량으로 객체를 생성해 내야 한다면, 당연히 생성자 함수를 사용하는 것이 효율적일 것이다.


메서드에서의 this

자바스크립트에서 객체의 프로퍼티인 함수를 메서드라고 부른다. 즉, 프로퍼티로서의 함수 === 메서드 인 것 이다. (물론 구분을 위해서 메서드라고 부르는 것이 좋다)

메서드에서 this는 메서드를 호출한 즉, 메서드를 소유하고 있는 객체 그 자신이 된다. 예를 들어 다음과 같다.

const ojbect ={
    name: 'kim',
    age:90,
    sum(){
        return '나는'+this.age+'살'
    }
}

console.log(ojbect.sum())
               ㄴ sum 메서드에서 this가 가리키는(바인딩한) 대상


이렇듯 this는 호출 방식에 따라 다양하게 바인딩 되는데 다음시간에는 이러한 바인딩을 강제적으로 명시하는 메서드에 대해 알아볼 것이다.

반응형