[JavaScript] this

this란 this를 포함하고 있는 함수 또는 메서드가 자신을 포함하고 있는 객체를 가리키도록 약속된 특수한 예약어다.

간단히 말하면 this는 자신을 호출하는것을 가리킨다.




this를 위에서 처럼 정의했지만 상황에 따라 조금씩 다르게 동작한다.


this는 일반 함수에서 사용할 때와 화살표 함수에서 사용할 때 다르게 동작한다.


일반 함수에서의 this는 호출할때의 환경에 따라 즉, 런타임 환경에서 this의 값이 동적으로 결정되는것이고

화살표함수에서의 this는 선언된 시점에서의 환경(lexical scoping)에 따라 정적으로 결정되는 것이다.

조금더 자세히 알아보면

상황에 따라 다르게 동작하는 this


1. 함수(메서드) 안에서의 this
// 함수 안에서의 this
function functionThis() {
console.log(this);
}
functionThis(); // window
(전역)함수를 선언하면 this는 window 객체를 가리킨다. 

함수가 전역에 선언되어있으면 해당 함수는 전역 객체인 Window 안에서 함수가 선언되는 것이기 때문에 함수이면서 동시에 메서드이다. 

위 함수(메서드)가 호출되면 함수 안에있는 console.log(this)는 해당 함수를 소유하고있는 객체인 window를 가리킨다는것을 알 수 있다.

여기서 메서드란 객체가 가지고 있는 함수를 말한다.

// 메서드 안에서의 this
let methodThis = {
test: true,
methodTest: function () {
console.log(this.test); // true
},
// methodTest() {
// console.log(this.test); 위의 메서드를 이와 같이 줄여서 작성할 수 있다.
// },
};

위와 같이 객체안에 메서드를 작성한 경우 메서드를 소유하고 있는 객체인 methidThis는 this가 가리키는 대상이 된다.


2. 전역 함수가아닌 외부함수안에 내부함수에서 호출한 this

function fruit() {
function apple() {
console.log(this);
}
apple();
}
fruit(); // Window

예제와 같이 fruit (전역)함수 안에 apple 함수안에서의 this는 Window를 가리킨다. 객체안의 함수가아닌 함수안의 함수에서의 this는 전역객체인 Window를 가리킨다.


3. 생성자로 호출된 this

function fruit(name) {
this.name = name;
console.log(this); // window
}
fruit("apple");

console.log(window.name); // apple
console.log(fruit.name); //fruit

위 함수에서의 this는 전역객체인 Window를 가리키기 때문에 window.name을 할 경우 매개변수로 들어온 apple이 출력된다.


function fruit(name) {
this.name = name;
}

let apple = new fruit("apple");
let banana = new fruit("banana");

console.log(window.name); // 빈 문자열 "" 이 출력
console.log(apple.name); // apple
console.log(banana.name); // banana

반면에 생성자 함수를 사용하게될경우 변수에 생성자 함수를 할당하게되는데 이때 할당되는 변수가 생성자 함수 내부에서의 this가 가리키는 객체가 된다. 

new 키워드를 사용하여 생성자함수를 호출하는 경우 함수 내부에서 this가 할당된 변수를 가리키게되므로 window.name을 하게 되면 빈 문자열을 반환한다. 

apple과 banana는 생성자 함수로 만들어진 객체이지만 완전히 별도의 객체이기 때문에 각 객체의 속성들은 서로 관련이 없다.


4. 화살표 함수 안에서의 this

화살표 함수의 경우 기존의 함수들과 다르게 this가 적용된다. 

일반 함수의 this는 함수를 호출할때 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 런타임 환경에서 동적으로 결정되지만 

화살표 함수에서의 this는 함수가 호출되는 시점이 아닌 선언된 시점에서 this가 가리키는 객체에 바인딩된다는 점이 다르다.

let apple = () => {
console.log(this);
};

let fruit = {
name: apple,
};

apple(); // Window
fruit.name(); //Window

바로 위 예제에서 화살표함수는 선언된 시점에서 this가 객체를 바인딩하므로 전역객체인 window를 가리키게된다.

fruit 객체안에 apple 함수를 메서드로 사용하더라도 this가 선언된 시점에서  this의 값이 결정되므로 메서드를 포함하고있는 객체 fruit을 가리키지 않으며 선언된 시점의 window를 가리킨다.

이외에도 기존의 this와 다르게 동작하는 점이 있다. 아래의 예제를 보자.

let fruit = {
name: () => {
console.log(this);
},
};

fruit.name(); //window

위 예제의 경우 메서드로 정의한 화살표 함수 내부의 this는 메서드를 소유한 객체, 즉 메서드를 호출한 객체인 fruit를 가리키지 않고 전역객체인 window를 가리킨다. 

그 이유는 화살표 함수는 화살표 함수가 아닌 화살표 함수를 둘러싸고 있는 외부 함수를 기준으로하여 this의 값을 결정한다.

따라서 화살표 함수로 메서드를 정의하는경우 원치않게 동작할 수 있으므로 

프로퍼피값으로 메서드를 정의할 때에는 화살표 함수 보다는 일반 함수를 사용하도록 하는것이 좋다.





댓글