Small Grey Outline Pointer [인간JS되기] 자바스크립트의 this
본문 바로가기
Dev./JavaScript

[인간JS되기] 자바스크립트의 this

by sso. 2023. 3. 23.

제로초님 인간JS되기 강의 보고 정리

 

 

 

자바스크립트의 this는 다른 언어에서의 this와 다르다

콘솔 로그로 this를 찍어보면 윈도우가 나온다

자바스크립트에서 this는 기본적으로 window라고 생각하면 된다

 

 

js(브라우저) - window(전역객체)

node - global(전역객체)

이었는데, 최근에는 둘 다 globalThis라는 것으로 합쳐졌다고 한다 

(if문으로 분기처리를 하지 않기 위해 통합 되었다고 함)

 

 

 


const obj = {
    name : 'soyoung',
    sayName(){
        console.log(this.name);
    }
};


obj.sayName(); // soyoung

 

이 때 this는 window를 가리키는 것이 아니라, obj객체를 가리킨다

하지만 항상 이렇게 적용 되는 것은 아니고 적절한 판단을 해야 한다

const sayN = obj.sayName; //sayN 에 obj.sayName을 대입해본다
sayN() // 빈칸이 나온다 window.name

 

this는 함수가 호출될 때 정해진다

this에 특별한 동작을 한 게 없다면, 기본적으로 window가 될 것

만약 함수를 호출하는데 함수 앞에 obj. 이런 식으로 함수 앞에 객체가 붙어있다면 this는 그 객체를 가리킨다

 

 

this가 달라지는 경우

 

화살표함수

//화살표 함수로 바꿔보기
const obj = {
    name : 'soyoung',
    sayName: ()=>{
        console.log(this.name);
    }
};

obj.sayName() //빈칸 (window.name)이 나온다

 

 

new연산자

new연산자를 사용해서 객체를 생성할 때

이 때 this는 객체 자기 자신이 된다

 

 

 

function sayName(){
    console.log(this.name);
}

sayName(); //window.name이 된다 (빈 값이 나옴)

위의 코드에서 this를 바꿔주는 방법에는 다음과 같다

 

sayName.bind
sayName.call
sayName.apply

 

bind / call / apply

이 세가지로 this를 바꿔줄 수 있다

 

 

bind

sayName.bind({name : 'soyoung'})()
//soyoung

.bind() 괄호안에 this를 바꾸고 싶은 객체를 넣어주고 ()괄호를 써주면 name 값이 출력 된다

이 때 this.name은 bind 안의 객체를 가리킬 것이다

bind는 새로운 함수를 만드는 것 뿐이라 호출을 할 때는 ()가 필요

 

 

apply

sayName.apply({name : 'ruru'})
//ruru

apply는 bind처럼 뒤에 ()가 붙지 않는다 => 함수를 바로 실행한다. 함수 생성과 호출까지 한번에 함

 

call

sayName.call({name : 'nunu'})
//nunu

 

 

기본적으로 this는 window이고, this가 바뀌는 경우에는 다음과 같다

함수 앞에 객체가 붙어서 호출될 때

객체의 메서드를 호출할 때

new 붙여서 호출할 때

bind / apply / call => 직접적으로 this를 변경해주는 경우

 

this는 랙시컬 스코프처럼 처음에 정해지는 것이 아니라, this는 함수를 호출할 때 정해진다

 


화살표 함수에서의 this 

const obj = {
    name : 'lulu',
    sayName: () => {
        console.log(this.name);
    }
}

obj.sayName();
//window.name

 

화살표함수에서의 this는 무조건 전역을 가리키는가?

화살표함수에서의 this는 부모 스코프를 가리키는데 스코프하면 호출이 아니라 선언을 떠올려야 한다!

 

const obj = {
    name : 'lulu',
    sayName: () => {
        console.log(this.name);
        function inner(){
            console.log(this.name);
        }
        inner();
    }
}

이 때 inner에 대한 스코프체인은 무엇일까

저번 강의에서 배웠던 것처럼 생각해보자

 

inner(); 이너 함수 앞에 직선을 그어서 위로 올라가본다

제일 먼저 만나는 것 sayName함수 

그렇다면 sayName함수는 어디에 닿이는가 (이 때 obj는 없다고 생각) -> anonymous 전역에 닿인다

 

랙시컬 스코프 찾기

inner -> sayName -> anonymous 

스코프체인이 어떻게 되어있는지 잘 파악해야 한다

스코프체인을 그리는 이유는 inner에서 다른 변수에 접근 가능한가의 여부를 알기위해

 

 

sayName의 this.name은 lulu가 나오지만,

inner 함수의 this.name은 window.name(빈 칸)이 나온다

 

this.name은 obj.sayName()을 호출할 때 실행된다

=> 함수 앞에 obj.가 붙었고(객체), sayName()화살표 함수가 아니므로 obj.name이 되는 것 (this가 obj를 가리키니까)

 

this.name는 함수 호출할 때의 기준으로 보면, inner() 함수를 호출만 하고 this를 바꿔주는 행동을 따로 하지 않았다

=> 따라서 이때의 this는 window가 된다 

 

this는 함수호출 될 때 정해진다

함수에서 this를 바꿔주는 행동을 했는가 아닌가로 this가 무엇을 가리키는지 정해진다

 

 


 

방금 전의 코드에서 inner를 화살표 함수로 바꾸고 결과를 확인해본다

이 때 inner의 this는 obj가 됐다 (inner의 this.name이 lulu로 나옴)

 

this가 어떻게 결정되는지 코드를 해석해보자

this는 함수를 호출할 때 this가 어떻게 되는지 정해진다

 

inner(); //함수가 호출 됨

inner() 함수를 호출할 때 this를 바꿔주는 행동을 하지 않았다

new

obj.메서드

call / apply / bind 

 

const inner = () =>{
            console.log(this.name);
        }

이 때 여기서 쓰인 화살표함수는 윈도우를 가져오는 것이 아닌, 부모함수의 this를 그대로 가져온다

그렇다면 inner함수의 부모를 찾아 가본다

 

const obj = {
    name : 'lulu',
    sayName(){
        console.log(this.name);
        const inner = () =>{
            console.log(this.name);
        }
        inner();
    }
}

sayName함수가 inner//화살표함수의 부모함수이다

그렇다면 sayName의 this는 어떻게 정해지는가? 함수가 호출될 때 정해진다

obj.sayName() //호출

sayName부모함수의 this는 obj가 된다

 

 

const obj = {
    name : 'lulu',
    sayName(){
        console.log(this.name);
        const inner = () =>{
            console.log(this.name);
        }
        inner();
    }
}

 

inner의 부모함수에서 this를 가져온다고 해도, 파란색 영역에서만 보면 sayName의 this를 찾기는 어렵다

왜냐? 위의 상황에서는 sayName함수를 호출하지 않았기 때문에 sayName의 this가 obj라고 단언할 수 없다.

 

inner의 부모함수를 찾아서 sayName블럭을 분석하려고 하면,

sayName블럭 자체를 보는게 아니라 sayName이 어떻게 호출 되었는지를 봐야 한다

 

따라서 this는 함수가 호출될 때 정해진다는 것을 잊지 말기!!!!

 

 

호출하는 위치가 아닌, 호출하는 방법에 따라 this가 달라진다

sayN() //기본적인 형태의 함수로 호출하면 window를 가르킨다

obj.sayName(); //호출할 때 객체를 붙여서 호출하면 this는 이 객체가 된다

 

 

 

 

728x90

댓글